3.1 主动对象
Active 对象是一种设计模式,它将方法的执行线程与调用它的线程分开。此模式的目的是使用异步方法调用和请求处理调度程序提供并行执行。
简化版:

经典变体:

该模板有六个元素:
- 为客户端的公共方法提供接口的代理对象。
- 定义活动对象访问方法的接口。
- 来自客户端的传入请求列表。
- 确定查询执行顺序的调度程序。
- 活动对象方法的实现。
- 客户端接收结果的回调过程或变量。
3.2 锁定
Lock 模式是一种同步机制,允许在多个线程之间独占访问共享资源。锁是执行并发控制策略的一种方式。

基本上,使用软锁,假设每个线程在访问相应的共享资源之前尝试“获取锁”。
然而,一些系统提供了强制锁定机制,通过在试图获得访问权限的线程上抛出异常来中止对锁定资源的未授权访问尝试。
信号量是最简单的锁类型。在数据访问方面,不区分访问模式:共享(只读)或独占(读写)。在共享模式下,多个线程可以请求一个锁来访问只读模式下的数据。独占访问模式也用于更新和删除算法。

锁的类型通过阻止线程继续执行的策略来区分。在大多数实现中,锁定请求会阻止线程继续执行,直到锁定的资源可用。
自旋锁是一种在循环中等待直到访问被授予的锁。如果线程等待锁的时间很短,这样的锁会非常有效,从而避免过多地重新安排线程。如果其中一个线程长时间持有锁,则等待访问的成本将很高。

要有效实现锁定机制,需要硬件层面的支持。硬件支持可以实现为一个或多个原子操作,例如“测试和设置”、“获取和添加”或“比较和交换”。此类指令允许您不间断地检查锁是否空闲,如果是,则获取锁。
3.3 监控
Monitor 模式是一种高级进程交互和同步机制,提供对共享资源的访问。一种使用公共资源(通常是硬件或一组变量)同步两个或多个计算机任务的方法。
在基于监视器的多任务处理中,编译器或解释器透明地将锁定-解锁代码插入到适当格式的例程中,对程序员透明,从而使程序员免于显式调用同步原语。

监控器包括:
- 一组与共享资源交互的过程
- 互斥量
- 与此资源关联的变量
- 定义条件以避免竞争条件的不变量
监控过程在开始工作之前获取互斥锁,并持有它直到过程退出或等待特定条件。如果每个过程在释放互斥量之前保证不变量为真,则没有任务可以在竞争条件下获取资源。
这就是synchronized运算符在 Java 中与wait()
and方法一起工作的方式notify()
。
3.4 双重检查锁定
双重检查锁定是一种并行设计模式,旨在减少获取锁的开销。
首先,在没有任何同步的情况下检查阻塞条件。仅当检查结果表明它需要获取锁时,线程才会尝试获取锁。
//Double-Checked Locking
public final class Singleton {
private static Singleton instance; //Don't forget volatile modifier
public static Singleton getInstance() {
if (instance == null) { //Read
synchronized (Singleton.class) { //
if (instance == null) { //Read Write
instance = new Singleton(); //
}
}
}
}
如何在线程安全的环境中创建单例对象?
public static Singleton getInstance() {
if (instance == null)
instance = new Singleton();
}
如果你从不同的线程创建一个Singleton对象,那么可能会出现同时创建几个对象的情况,这是不可接受的。因此,将对象创建包装在同步语句中是合理的。
public static Singleton getInstance() {
synchronized (Singleton.class) {
if (instance == null)
instance = new Singleton();
}
}
这种方法会奏效,但它有一个小缺点。对象创建后,以后每次尝试获取它时,都会在synchronized块中进行一次检查,这意味着当前线程和与之连接的一切都将被锁定。所以这段代码可以稍微优化一下:
public static Singleton getInstance() {
if (instance != null)
return instance;
synchronized (Singleton.class) {
if (instance == null)
instance = new Singleton();
}
}
在某些语言和/或某些机器上,无法安全地实现此模式。因此,它有时被称为反模式。这样的特性导致了Java内存模型和C++内存模型中出现了“happens before”的严格顺序关系。
它通常用于减少在多线程程序中实现惰性初始化的开销,例如 Singleton 设计模式。在变量的惰性初始化中,初始化被推迟到计算中需要变量的值时。
3.5 调度器
Scheduler是一种并行设计模式,它提供了一种实现调度策略的机制,但独立于任何特定的策略。使用显式指定等待线程序列的对象,控制线程执行顺序代码的顺序。

GO TO FULL VERSION