本文主要是介绍synchronized wait()/notify 对比 ReentrantLock await()/signal(),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
结论
synchronized
synchronized 配合 wait()/notify 无法实现精准唤醒线程
ReentrantLock
ReentrantLock 配合 Condition await()/signal() 可以实现精准唤醒线程 (指唤醒指定的线程)
ReentrantLock 如何实现精准唤醒线程
一个 lock 配合多个 Condition, 且每个 Condition 中只有一个线程
(若一个Condition中有多个线程,也无法精准唤醒线程)
案例 synchronized
public class ManySync {public void await1() {synchronized (this) {try {System.out.println("await1 - 进入等待" + Thread.currentThread().getName());this.wait();System.out.println("await1 - 被唤醒" + Thread.currentThread().getName());} catch (Exception e) {e.printStackTrace();}}}public synchronized void await2() {synchronized (this) {try {System.out.println("await2 - 进入等待" + Thread.currentThread().getName());this.wait();System.out.println("await2 - 被唤醒" + Thread.currentThread().getName());} catch (Exception e) {e.printStackTrace();}}}public void await3() {synchronized (this) {try {System.out.println("await3 - 进入等待" + Thread.currentThread().getName());this.wait();System.out.println("await3 - 被唤醒" + Thread.currentThread().getName());} catch (Exception e) {e.printStackTrace();}}}public void await4() {synchronized (this) {try {System.out.println("await4 - 进入等待" + Thread.currentThread().getName());this.wait();System.out.println("await4 - 被唤醒" + Thread.currentThread().getName());} catch (Exception e) {e.printStackTrace();}}}public void notif() {synchronized(this) {try {this.notify();this.notify();this.notify();this.notify();} catch (Exception e) {e.printStackTrace();}}}}class Run3 {public static void main(String[] args) {try {ManySync manySync = new ManySync();Thread t1 = new Thread(() -> {manySync.await1();});Thread t2 = new Thread(() -> {manySync.await2();});Thread t3 = new Thread(() -> {manySync.await3();});Thread t4 = new Thread(() -> {manySync.await4();});t1.start();Thread.sleep(200);t2.start();Thread.sleep(200);t3.start();Thread.sleep(200);t4.start();Thread.sleep(1000);manySync.notif();} catch (Exception e) {e.printStackTrace();}}
}
输出结果 可以看出等待时间长的锁并不会最先被唤醒, 也无法唤醒指定线程,(因为并未提供能唤醒的API,也无法进行设计) 唤醒的输出结果是随机的 由 JVM 调度
await1 - 进入等待Thread-0
await2 - 进入等待Thread-1
await3 - 进入等待Thread-2
await4 - 进入等待Thread-3
await1 - 被唤醒Thread-0
await4 - 被唤醒Thread-3
await3 - 被唤醒Thread-2
await2 - 被唤醒Thread-1
案例 ReentrantLock
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class ManyCondition {private Lock lock = new ReentrantLock();Condition condition1 = lock.newCondition();Condition condition2 = lock.newCondition();Condition condition3 = lock.newCondition();Condition condition4 = lock.newCondition();public void await1() {try {lock.lock();System.out.println("await1 - 进入等待" + Thread.currentThread().getName());condition1.await();System.out.println("await1 - 被唤醒" + Thread.currentThread().getName());lock.unlock();} catch (Exception e) {e.printStackTrace();}}public void await2() {try {lock.lock();System.out.println("await2 - 进入等待" + Thread.currentThread().getName());condition2.await();System.out.println("await2 - 被唤醒" + Thread.currentThread().getName());lock.unlock();} catch (Exception e) {e.printStackTrace();}}public void await3() {try {lock.lock();System.out.println("await3 - 进入等待" + Thread.currentThread().getName());condition3.await();System.out.println("await3 - 被唤醒" + Thread.currentThread().getName());lock.unlock();} catch (Exception e) {e.printStackTrace();}}public void await4() {try {lock.lock();System.out.println("await4 - 进入等待" + Thread.currentThread().getName());condition4.await();System.out.println("await4 - 被唤醒" + Thread.currentThread().getName());lock.unlock();} catch (Exception e) {e.printStackTrace();}}public void signal() {try {lock.lock();System.out.println("await1 - 被唤醒 - " + Thread.currentThread().getName());condition1.signal();lock.unlock();lock.lock();System.out.println("await2 - 被唤醒 - " + Thread.currentThread().getName());condition2.signal();lock.unlock();lock.lock();System.out.println("await3 - 被唤醒 - " + Thread.currentThread().getName());condition3.signal();lock.unlock();lock.lock();System.out.println("await4 - 被唤醒 - " + Thread.currentThread().getName());condition4.signal();lock.unlock();} catch (Exception e) {e.printStackTrace();}}}class Run2 {public static void main(String[] args) {try {ManyCondition manyCondition = new ManyCondition();Thread t1 = new Thread(() -> {manyCondition.await1();});Thread t2 = new Thread(() -> {manyCondition.await2();});Thread t3 = new Thread(() -> {manyCondition.await3();});Thread t4 = new Thread(() -> {manyCondition.await4();});t1.start();t2.start();t3.start();t4.start();Thread.sleep(2000);manyCondition.signal();} catch (Exception e) {e.printStackTrace();}}
}
输出结果 这里可以看出 ,当每个Condition 中只有一个线程时, 可以通过逻辑控制, 实现精准唤醒需要唤醒的线程
await1 - 进入等待Thread-0
await2 - 进入等待Thread-1
await3 - 进入等待Thread-2
await4 - 进入等待Thread-3
await1 - 被唤醒 - main
await2 - 被唤醒 - main
await3 - 被唤醒 - main
await4 - 被唤醒 - main
await1 - 被唤醒Thread-0
await2 - 被唤醒Thread-1
await3 - 被唤醒Thread-2
await4 - 被唤醒Thread-3
这篇关于synchronized wait()/notify 对比 ReentrantLock await()/signal()的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!