Java教程之使用Lock取代synchronized
在多线程中,1.5版本之前,我们都使用同步代码块或者同步方法来解决线程安全问题
比如:
同步代码块
synchronized(锁对象){
功能代码;
}
同步方法
public synchronized void test(){
功能代码;
}
在1.5版本,在java的工具类包中,java.util.concurrent.locks 中,推出了最新的
解决线程安全的方法,就是Lock+Condition的方式,
那这两种方式之间的关系和区别是什么呢?
加入对于线程常见的生产者消费者模式,我们使用两种方式实现,来看看他们的区别:
第一种,使用synchronized
我们完成一个男人挣钱女人花的例子
需求是如果没钱,男人线程挣一次钱,等待,然后唤醒女人去花钱,花完钱,等待,唤醒
男人去挣钱,一直循环这个过程,将男人线程看做生产线程,女人线程看做消费线程。
代码如下:
//首先完成共享数据
class Person{
String name;
boolean isMoney=true;
//挣钱
public void zhengQian(){
synchronized(this){
while(!isMoney){
try{wait();}catch(Exception e){}
}
name="男人";
System.out.println(Thread.currentThread().getName()+name+"---挣钱---");
isMoney=!isMoney;
notifyAll();//叫醒所有
}
}
//花钱
public void huaQian(){
synchronized(this){
while(isMoney){
try{wait();}catch(Exception e){}
}
name="women。。。。人";
System.out.println(Thread.currentThread().getName()+name+"---花=========钱---");
isMoney=!isMoney;
notifyAll();//叫醒所有
}
}
}
//输入线程
class In implements Runnable{
Person p=null;
In(Person p){
this.p=p;
}
public void run(){
while(true){
p.zhengQian();
}
}
}
//输出线程
class Out implements Runnable{
Person p=null;
Out(Person p){
this.p=p;
}
public void run(){
while(true){
p.huaQian();
}
}
}
从代码中可以看出,对于同步代码块或者同步方法来说,都是以锁对象this来控制其锁定的代码的。
api中也告诉我们:
Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。此实现允许更灵活的结构,可以具有差别很大的属性,可以支持多个相关的 Condition 对象。
那使用Lock+Condition怎么来实现呢?
代码如下:
import java.util.concurrent.locks.*;
class Person{
String name;
boolean isMoney=true;
Lock lock=new ReentrantLock();
Condition in=lock.newCondition();
Condition out=lock.newCondition();
//挣钱
public void zhengQian(){
lock.lock();
try{
while(!isMoney){
try{in.wait();}catch(Exception e){}
}
name="男人";
System.out.println(Thread.currentThread().getName()+name+"---挣钱---");
isMoney=!isMoney;
out.signal();//叫醒对方
}finally{
lock.unlock();
}
}
//花钱
public void huaQian(){
lock.lock();
try{
while(!isMoney){
try{out.wait();}catch(Exception e){}
}
name="women。。。。人";
System.out.println(Thread.currentThread().getName()+name+"---花=========钱---");
isMoney=!isMoney;
in.signal();//叫醒对方
}finally{
lock.unlock();
}
}
}
对比发现,Lock+Condition的方式是使用Condition对象来具体操作现场的等待和唤醒的,
也就是对于生产线程有专属的生成线程的Condition对象,对消费线程有专属的消费线程的Condition
对象,当等待或者唤醒时可以精确的控制是哪方线程,同步代码块或者同步方法在唤醒时,不能精确的
唤醒对方,所以只能唤醒全部,这时候增加了线程的判断次数,明显,Lock+Condition是优于synchronized的方式的
接下来我们分析下Lock和Condition的关系
Lock的子类对象是来取代synchronized的,也就是锁,Condition只是锁的操作对象
取代的是以前的锁对象,都拥有等待和唤醒的方法,虽然名字不同,Condition主要是对锁的操作对象
进行分类,如下图:
上图中,一个Lock对象,创建出来三个Condition对象 x,y,z
也就是以后执行这个锁的线程将会被分成三类线程,比如如果执行x.await(),执行这段代码的
三个绿色线程将会进入等待状态,再比如z中三个红色线程都处于等待状态,如果执行z.signal(),将会唤醒执行z的三个红色线程中的某一个,这样代码就可以正常运行了。
蓝色线两侧分别表示两个Lock的子类对象,每一个lock的Condition之间可以互相操作,对于两个
锁之间的Condition,比如,x和Q,就没有直接的关系了
好了,这篇文章主要说明下Lock+Condition方式来取代synchronized,希望对大家有所帮助。
千锋Java培训作为中国IT研发人才一体化服务的开拓者,为学生制定合理有序的学习计划,0学费入学,2周免费试听不满意不收费,与学员签订就业协议,坚持良心面授,从千锋Java培训班出去的学员均已高薪就业。千锋推出的免费java视频教程,让学员能够方面的巩固基础技术能力。
猜你喜欢LIKE
相关推荐HOT
更多>>如何写出高质量Java代码?看看这篇高标准代码开发规范吧
新手在学习和开发过程中,不可避免的会发生一些莫名其妙的问题;凭习惯编写代码,后续再重构优化代码,重走旧路,延缓了开发能力的提高。无论哪...详情>>
2023-02-15 19:16:44实战干货|Spring Boot整合MyBatis框架快速实现数据操作
在开发中,我们通常会对数据库的数据进行操作,Sprirng Boot对关系型数据库和非关系型数据库的访问操作都提供了非常好的整合支持。详情>>
2023-02-07 17:19:53开发实操|微信支付流程图文详解
微信支付是腾讯集团旗下的第三方支付平台。微信支付为各类企业以及小微商户提供专业的收款能力,运营能力,资金结算解决方案,以及安全保障。用...详情>>
2023-01-18 14:22:55带你玩转ssm项目 - 锋迷汽车管理
千锋科技针针对汽车做了管理系统,管理系统中不仅有客户的管理还有车辆租赁的管理,租赁车辆公司对于租车的流程,租车过程的问题,对于客户的维...详情>>
2023-01-18 11:47:47一文带你快速入门Activiti7工作流引擎
之前接到过一个需求,为某公司内部系统设计一个工作流引擎来解决公司内部的各种自动化流程审批业务。当时,就在想,对于流程审批来说,每个申请...详情>>
2023-01-10 10:54:47Java培训问答更多>>
新Java行业疑惑解答:Java的内存管理是如何工作的?
新java script是什么?为什么要学java script
新java和大数据哪个好?未来哪个职业发展更好
新java培训班多久能学会?培训周期大概多久
新java script和java的区别有哪些?如何区分
新java script的数据类型主要有哪些?怎样学的更快
新c语言与java区别在哪里?去培训机构学哪个比较好
Java面试题库 更多>>
华为外包java面试题-Java实现单链表的逆序
Java程序员面试题
Java面试题及答案
什么是线程的上下文切换?
如何撤销已经推送(push)到远端仓库的提交(commit)信息?
你了解哪些加密算法?
- 北京校区
- 大连校区
- 广州校区
- 成都校区
- 杭州校区
- 长沙校区
- 合肥校区
- 南京校区
- 上海校区
- 深圳校区
- 武汉校区
- 郑州校区
- 西安校区
- 青岛校区
- 重庆校区
- 太原校区
- 沈阳校区
- 南昌校区
- 哈尔滨校区