同步模式之顺序控制
固定运行顺序
public static final Object lock = new Object();
public static void main(String[] args) {
Thread thread1 = new Thread(()->{
while (true){
synchronized (lock){
try {
Thread.sleep(1000);
log.debug("1");
lock.notify();
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
}
}
}
});
Thread thread2 = new Thread(()->{
while (true){
synchronized (lock){
try {
Thread.sleep(1000);
log.debug("2");
lock.notify();
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
}
}
}
});
thread1.start();
thread2.start();
}
交替输出
Lock公平锁
public static final ReentrantLock lock = new ReentrantLock(true);
public static void main(String[] args) {
Thread thread1 = new Thread(()->{
for (int i = 0; i < 5; i++) {
try {
lock.lock();
System.out.print("a");
}finally {
lock.unlock();
}
}
});
Thread thread2 = new Thread(()->{
for (int i = 0; i < 5; i++) {
try {
lock.lock();
System.out.print("b");
}finally {
lock.unlock();
}
}
});
Thread thread3 = new Thread(()->{
for (int i = 0; i < 5; i++) {
try {
lock.lock();
System.out.print("c");
}finally {
lock.unlock();
}
}
});
thread1.start();
thread2.start();
thread3.start();
}
wait/notify版
public static void main(String[] args) {
WaitNotify waitNotify = new WaitNotify(1,10);
Thread thread1 = new Thread(()->{
waitNotify.print("a",1,2);
});
Thread thread2 = new Thread(()->{
waitNotify.print("b",2,3);
});
Thread thread3 = new Thread(()->{
waitNotify.print("c",3,1);
});
thread1.start();
thread2.start();
thread3.start();
}
}
class WaitNotify{
//等待标记
private int flag;
//循环次数
private int loopNumber;
public WaitNotify(int flag, int loopNumber) {
this.flag = flag;
this.loopNumber = loopNumber;
}
//打印方法
public synchronized void print(String content,int waitFlag,int nextFlag){
for (int i = 0; i < loopNumber; i++) {
while (flag != waitFlag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(content);
flag = nextFlag;
this.notifyAll();
}
}
await/signal
public static void main(String[] args) throws InterruptedException {
AwaitSignal awaitSignal = new AwaitSignal(5);
Condition A = awaitSignal.newCondition();
Condition B = awaitSignal.newCondition();
Condition C = awaitSignal.newCondition();
Thread thread1 = new Thread(()->{
awaitSignal.print("a",A,B);
});
Thread thread2 = new Thread(()->{
awaitSignal.print("b",B,C);
});
Thread thread3 = new Thread(()->{
awaitSignal.print("c",C,A);
});
thread1.start();
thread2.start();
thread3.start();
Thread.sleep(1000);
try {
awaitSignal.lock();
A.signal();
}finally {
awaitSignal.unlock();
}
}
}
class AwaitSignal extends ReentrantLock{
private int loopNumber;
public AwaitSignal(int loopNumber) {
this.loopNumber = loopNumber;
}
public void print(String content,Condition current,Condition next){
for (int i = 0; i < loopNumber; i++) {
lock();
try {
current.await();
System.out.print(content);
next.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
unlock();
}
}
}
}
本章小结
本章我们需要重点掌握的是
- 分析多线程访问共享资源时,哪些代码片段属于临界区
- 使用 synchronized 互斥解决临界区的线程安全问题
- 掌握 synchronized 锁对象语法
- 掌握 synchronzied 加载成员方法和静态方法语法
- 掌握 wait/notify 同步方法
- 使用 lock 互斥解决临界区的线程安全问题 掌握 lock 的使用细节:可打断、锁超时、公平锁、条件变量
- 学会分析变量的线程安全性、掌握常见线程安全类的使用
- 了解线程活跃性问题:死锁、活锁、饥饿
- 应用方面
- 互斥:使用 synchronized 或 Lock 达到共享资源互斥效果,实现原子性效果,保证线程安全。
- 同步:使用 wait/notify 或 Lock 的条件变量来达到线程间通信效果。
- 原理方面
- monitor、synchronized 、wait/notify 原理
- synchronized 进阶原理
- park & unpark 原理
- 模式方面
- 同步模式之保护性暂停
- 异步模式之生产者消费者
- 同步模式之顺序控制