通过Lock对象以及Condition对象实现多线程同步
Posted 技术专家
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过Lock对象以及Condition对象实现多线程同步相关的知识,希望对你有一定的参考价值。
通过Lock对象以及Condition对象实现多线程同步:
在之前的学习中,无论是通过synchronized建立同步代码块,还是通过synchronized建立同步函数,都是把对象看成一把锁来实现同步,这种解释有点牵强,而且在消费者—生产者的那个实例中,其实还有个问题,那就是在避免线程全部冻结时,没必要把相同功能的线程解冻,只要把其他功能的线程解冻即可,也就是说消费者线程只要解冻生产者线程即可,没必要把其他消费者线程也解冻,为了解决这些问题,java1.5版本推出了同步的升级办法,那就是通过Lock对象和Condition对象实现同步。
新的同步办法不再需要synchronized关键字,而引入了更加形象的Lock。
Lock实质上是是一个接口,在创建对象时,使用Lock的子类ReentrantLock来建立对象。
使用方法:建立对象后,在需要同步的代码前一行写 Lock对象.lock(); ,在同步代码后一行写 Lock对象.unlock();
Lock对象用来控制线程的进出,而对线程的操作则由Condition对象来操作;
对应关系:
wait——await(两者均抛出异常)
notify——signal
notifyAll——signalAll
Condition同样是接口,建立方法(比较神奇) Condition 对象名=Lock对象.newCondition();
例如:1-9 个数,A线程执行123.然后由B线程接着执行456.最后在由A线程执行789
代码:
package com.huojg.test; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /* * * 1-9 个数,A线程执行123.然后由B线程接着执行456.最后在由A线程执行789 * * * **/ public class lock { static class NumberWrapper { public int value = 1; } public static void main(String[] args) { //初始化可重入锁 final Lock lock=new ReentrantLock(); //第一个条件当屏幕上输出到3 final Condition reachThreeCondition=lock.newCondition(); //第一个条件当屏幕上输出到6 final Condition reachSixCondition=lock.newCondition(); //NumberWrapper只是为了封装一个数字,一边可以将数字对象共享,并可以设置为final //注意这里不要用Integer, Integer 是不可变对象 final NumberWrapper num = new NumberWrapper(); //初始化A线程 Thread threadA=new Thread( new Runnable() { public void run() { //需要先获得锁 lock.lock(); try { System.out.println("threadA start write"); while (num.value<=3) { System.out.println(num.value); num.value++; } //输出到3时要signal,告诉B线程可以开始了 reachThreeCondition.signal(); } finally{ lock.unlock(); } lock.lock(); try { //等待输出6的条件 reachSixCondition.await(); System.out.println("threadA start write"); //输出剩余数字 while (num.value <= 9) { System.out.println(num.value); num.value++; } } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } }); Thread threadB =new Thread(new Runnable() { public void run() { try { lock.lock(); while (num.value<=3) { //等待3输出完毕的信号 reachThreeCondition.await(); } }catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } try { lock.lock(); //已经收到信号,开始输出4,5,6 System.out.println("threadB start write"); while (num.value <= 6) { System.out.println(num.value); num.value++; } //4,5,6输出完毕,告诉A线程6输出完了 reachSixCondition.signal(); } finally{ lock.unlock(); } } }); //启动两个线程 threadB.start(); threadA.start(); } }
结果:
threadA start write 1 2 3 threadB start write 4 5 6 threadA start write 7 8 9
Condition对象的优势在于,signal只能唤醒被相同Condition对象的await方法冻结的线程,因此,可以建立多个Condition对象,分别用来冻结和解冻不同功能的线程
最后要注意的是,Lock接口属于类包Java.util.concurrent.locks
以上是关于通过Lock对象以及Condition对象实现多线程同步的主要内容,如果未能解决你的问题,请参考以下文章