当前位置: 代码迷 >> 综合 >> JUC学习系列四(条件锁 condition)
  详细解决方案

JUC学习系列四(条件锁 condition)

热度:21   发布时间:2023-12-28 12:35:46.0

ConditionObject 监视器方法(waitnotifynotifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。

Condition 实例实质上被绑定到一个锁上。要为特定 Lock 实例获得 Condition 实例,请使用其 newCondition() 方法。Condition 实现可以提供不同于 Object 监视器方法的行为和语义,比如受保证的通知排序,或者在执行通知时不需要保持一个锁。

情景一:三个线程,线程1打印A,线程2打印B,线程3打印C

public class ThreeRun {public void printB() {System.out.println("B");}public void printA() {System.out.println("A");}public void printC() {System.out.println("C");}public static void main(String[] args) {ThreeRun threeRun = new ThreeRun();A a = new A(threeRun);B b = new B(threeRun);C c = new C(threeRun);new Thread(a).start();new Thread(b).start();new Thread(c).start();}static   class A implements Runnable {private ThreeRun threeRun;public A(ThreeRun threeRun) {this.threeRun = threeRun;}@Overridepublic void run() {while (true) {threeRun.printA();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}}}}static class B implements Runnable {private ThreeRun threeRun;public B(ThreeRun threeRun) {this.threeRun = threeRun;}@Overridepublic void run() {while (true) {threeRun.printB();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}}}}static  class C implements Runnable {private ThreeRun threeRun;public C(ThreeRun threeRun) {this.threeRun = threeRun;}@Overridepublic void run() {while (true) {threeRun.printC();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}}}}}

场景二、三个线程,线程1打印A,线程2打印B,线程3打印C   (保证顺序打印,ABCABC....)

public class ThreeRun2 {//用作判断的信号 0执行A,1执行B,2执行Cprivate int single=0;public synchronized void printB() {while (single!=1){try {//本线程等待  释放锁wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("B");//增量,保证顺序性single++;//通知其他的线程notifyAll();}public synchronized void printA() {while (single!=0){try {wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("A");single++;notifyAll();}public synchronized void printC() {while (single!=2){try {wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("C");//为保证紧接着打印A,将增量清零single=0;notifyAll();}public static void main(String[] args) {ThreeRun2 threeRun = new ThreeRun2();A a = new A(threeRun);B b = new B(threeRun);C c = new C(threeRun);new Thread(a).start();new Thread(b).start();new Thread(c).start();}static   class A implements Runnable {private ThreeRun2 threeRun;public A(ThreeRun2 threeRun) {this.threeRun = threeRun;}@Overridepublic void run() {while (true) {threeRun.printA();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}}}}static class B implements Runnable {private ThreeRun2 threeRun;public B(ThreeRun2 threeRun) {this.threeRun = threeRun;}@Overridepublic void run() {while (true) {threeRun.printB();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}}}}static  class C implements Runnable {private ThreeRun2 threeRun;public C(ThreeRun2 threeRun) {this.threeRun = threeRun;}@Overridepublic void run() {while (true) {threeRun.printC();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}}}}}

场景三、三个线程,线程1打印A,线程2打印B,线程3打印C   (保证顺序打印,ABCABC....  换用condition的方式实现)

public class ThreeRun3 {private int single=0;//Condition是一个接口,在ReentrantLock里有实现Lock lock=new ReentrantLock();//分别获取三个条件锁Condition a=lock.newCondition();Condition b=lock.newCondition();Condition c=lock.newCondition();public  void printB() {lock.lock();while (single!=1){try {//相当于Object的wait()b.await();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("B");single++;//相当于nodifyAll()c.signal();lock.unlock();}public   void printA() {lock.lock();while (single!=0){try {a.await();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("A");single++;b.signal();lock.unlock();}public   void printC() {lock.lock();while (single!=2){try {c.await();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("C");single=0;a.signal();lock.unlock();}public static void main(String[] args) {ThreeRun3 threeRun = new ThreeRun3();A a = new A(threeRun);B b = new B(threeRun);C c = new C(threeRun);new Thread(a).start();new Thread(b).start();new Thread(c).start();}static   class A implements Runnable {private ThreeRun3 threeRun;public A(ThreeRun3 threeRun) {this.threeRun = threeRun;}@Overridepublic void run() {while (true) {threeRun.printA();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}}}}static class B implements Runnable {private ThreeRun3 threeRun;public B(ThreeRun3 threeRun) {this.threeRun = threeRun;}@Overridepublic void run() {while (true) {threeRun.printB();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}}}}static  class C implements Runnable {private ThreeRun3 threeRun;public C(ThreeRun3 threeRun) {this.threeRun = threeRun;}@Overridepublic void run() {while (true) {threeRun.printC();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}}}}}

 

使用说明:这个是API中给出的实例说明

condition要和Lock锁的实现类一起使用。

unlock()要与finally代码块一起使用。

await()要与Object的wait()区分开。

 

Condition是一个接口,在ReentrantLock里面的Sync用到了。它的实现类其实在AbstractQueuedSynchronizer里面的ConditionObject内部类。而该实现类里面有使用到了AQS的另一个内部类Node,这是一个双向链表的数据结构实现类。真是一环扣一环啊,condition使用虽然简单,但是当初实现它时并不简单。如果有很好的数据结构基础,读这个源码应该轻松一些。但是我感觉有点吃力,等恶补了数据结构这方面后,再回来补充condition的源码剖析。

 

  相关解决方案