千锋教育-做有情怀、有良心、有品质的职业教育机构

手机站
千锋教育

千锋学习站 | 随时随地免费学

千锋教育

扫一扫进入千锋手机站

领取全套视频
千锋教育

关注千锋学习站小程序
随时随地免费学习课程

首页 视频教程 培训课程 师资团队 技术干货 常见问题 面试题 职场就业 零基础学Java 行业资讯
【热点话题】 Java技术干货 Java学习教程 Java学习笔记 Java面试题 Java培训问答 Java培训机构哪些好 Java职场就业
当前位置:Java培训  >  java技术干货  >  Java教程之使用Lock取代synchronized

Java教程之使用Lock取代synchronized

来源:千锋教育
发布人:千锋老师
时间: 2018-08-01 09:19:00 1533086340

  在多线程中,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主要是对锁的操作对象

  进行分类,如下图:

1

  上图中,一个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

最新文章NEW

相关推荐HOT

更多>>
开班信息
北京校区
  • 北京校区
  • 大连校区
  • 广州校区
  • 成都校区
  • 杭州校区
  • 长沙校区
  • 合肥校区
  • 南京校区
  • 上海校区
  • 深圳校区
  • 武汉校区
  • 郑州校区
  • 西安校区
  • 青岛校区
  • 重庆校区
  • 太原校区
  • 沈阳校区
  • 南昌校区
  • 哈尔滨校区

14天品质课程免费学

10年以上业内强师带你蜕变精英

提交领取