Single Threaded Execution模式
所谓Single Threaded Execution模式,意即“以一个线程执行”。就像独木桥同一时间只允许一个人通行一样,该模式用于设置限制,以确保同一时间内只能让一个线程执行处理。
Single Threaded Execution 有时候又被称作为临界区或临界域。Single Threaded Execution这个名称侧重于执行处理的线程,而临界区或临界域的名称侧重于执行范围。
不使用Single Threaded Execution模式的程序
类的一览表
名字 | 说明 |
---|---|
Main | 创建门,并让三个人不断通过的类 |
Gate | 表示门的类。 它会在人们通过门时记录其姓名与出生地 |
UserThread | 表示人的类。人们将不断地通过门 |
Main类
Main类将创建一个门,并让三个人不断地通过。首先Main类会创建Gate类的实例,并将该实例作为参数传递个UserThread类的构造函数。
1 | public class Main { |
非线程安全的Gate类
Gate类表示人通过的门。
1 | public class Gate { |
UserThread类
UserThread表示不断通过门的人
1 | public class UserThread extends Thread { |
为什么会出错
因为pass方法会被多个线程执行,此处是3个。pass方法包含下面四条语句:
1 | this.counter++ |
这里以两个线程举两个错误的例子。
线程Alice和线程Bobby执行pass方法的情形1
线程Alice | 线程Bob | this.name的值 | this.address的值 |
---|---|---|---|
this.counter++ | this.counter++ | (之前的值) | (之前的值) |
“Bobby” | (之前的值) | ||
this.name = name | “Alice” | (之前的值) | |
this.address = address | “Alice” | “Alaska” | |
this.address = address | “Alice” | “Brazil” | |
check() | check() | “Alice” | “Brazil” |
***** BROKEN ***** |
|||
线程Alice和线程Bobby执行pass方法的情形2 |
线程Alice | 线程Bob | this.name的值 | this.address的值 |
---|---|---|---|
this.counter++ | this.counter++ | (之前的值) | (之前的值) |
this.name = name | “Alice” | (之前的值) | |
this.name = name | “Bobby” | (之前的值) | |
this.address = address | “Bobby” | “Brazil” | |
this.address = address | “Bobby” | “Alaska” | |
check() | check() | “Bobby” | “Brazil” |
***** BROKEN ***** |
使用Single Threaded Execution模式的程序
这边只要将Gate类改为线程安全的类即可,其他的类不需要修改。
线程安全的Gate类
分别有两处修改,在pass和toString方法签名中加入了synchronized关键字,这样一来Gate类就变成了线程安全的类。
1 | public class Gate { |
如图所示: 无论执行多久,都不会再有其他输出。
线程Alice和线程Bobby执行pass方法的情形1
线程Alice | 线程Bob | this.name的值 | this.address的值 |
---|---|---|---|
获取锁 | |||
this.counter++ | (之前的值) | (之前的值) | |
this.name = name | “Alice” | (之前的值) | |
this.address = address | “Alice” | “Alaska” | |
check() | “Alice” | “Alaska” | |
释放锁 | |||
获取锁 | |||
this.count++ | “Alice” | “Alaska” | |
this.name = name | “Bobby” | “Alaska” | |
this.address = address | “Bobby” | “Brazil” | |
check() | “Bobby” | “Brazil” | |
释放锁 |
线程Alice和线程Bobby执行pass方法的情形2
线程Alice | 线程Bob | this.name的值 | this.address的值 |
---|---|---|---|
获取锁 | |||
this.counter++ | (之前的值) | (之前的值) | |
this.name = name | “Bobby” | (之前的值) | |
this.address = address | “Bobby” | “Brazil” | |
check() | “Bob” | “Brazil” | |
释放锁 | |||
获取锁 | |||
this.count++ | “Bobby” | “Brazil” | |
this.name = name | “Alice” | “Brazil” | |
this.address = address | “Alice” | “Alaska” | |
check() | “Alice” | “Alaska” | |
释放锁 |
参考
《图解Java多线程设计模式》