Java 中怎么防止在线程阻塞与唤醒时死锁

发布时间:2021-07-24 13:53:06 作者:Leah
来源:亿速云 阅读:222

本篇文章为大家展示了Java 中怎么防止在线程阻塞与唤醒时死锁,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

Java并发编程:多线程如何实现阻塞与唤醒  说到suspend与resume组合有死锁倾向,一不小心将导致很多问题,甚至导致整个系统崩溃。接着看另外一种解决方案,我们可以使用以对象为目标的阻塞,即利用Object类的wait()和notify()方法实现线程阻塞。当线程到达监控对象时,通过wait方法会使线程进入到等待队列中。而当其它线程调用notify时则可以使线程重新回到执行队列中,得以继续执行

Java 中怎么防止在线程阻塞与唤醒时死锁

 思维不同

针对对象的阻塞编程思维需要我们稍微转变下思维,它与面向线程阻塞思维有较大差异。如前面的suspend与resume只需在线程内直接调用就能完成挂起恢复操作,这个很好理解。而如果改用wait与notify形式则是通过一个object作为信号,可以将其看成是一堵门。object的wait()方法是锁门的动作,notify()是开门的动作。某一线程一旦关上门后其他线程都将阻塞,直到别的线程打开门。

Java 中怎么防止在线程阻塞与唤醒时死锁

如图所示,一个对象object调用wait()方法则像是堵了一扇门。线程一、线程二都将阻塞,然后线程三调用object的notify()方法打开门,准确地说是调用了notifyAll()方法,notify()仅仅能让线程一或线程二其中一条线程通过)。最终线程一、线程二得以通过。

 死锁问题解决了吗?

使用wait与notify能在一定程度上避免死锁问题,但并不能完全避免,它要求我们必须在编程过程中避免死锁。在使用过程中需要注意的几点是:

 改进例子

我们通过wait与notify改造前面的例子,代码如下。改造的思想就是在MyThread中添加一个标识变量,一旦变量改变就相应地调用wait和notify阻塞唤醒线程。由于在执行wait后将释放synchronized(this)锁住的对象锁,此时System.out.println("running….");早已执行完毕,System类out对象不存在死锁问题。

Java 中怎么防止在线程阻塞与唤醒时死锁

Java 中怎么防止在线程阻塞与唤醒时死锁

 Park与UnPark

wait与notify组合的方式看起来是个不错的解决方式,但其面向的主体是对象object,阻塞的是当前线程,而唤醒的是随机的某个线程或所有线程,偏重于线程之间的通信交互。假如换个角度,面向的主体是线程的话,我就能轻而易举地对指定的线程进行阻塞唤醒,这个时候就需要LockSupport,它提供的park与unpark方法分别用于阻塞和唤醒.而且它提供避免死锁和竞态条件,很好地代替suspend和resume组合。

Java 中怎么防止在线程阻塞与唤醒时死锁

用park与unpark改造上述例子,代码如下。把主体换成线程进行的阻塞看起来貌似比较顺眼,而且由于park与unpark方法控制的颗粒度更加细小,能准确决定线程在某个点停止,进而避免死锁的产生。例如此例中在执行System.out.println前线程就被阻塞了,于是不存在因竞争System类out对象而产生死锁,即便在执行System.out.println后线程才阻塞也不存在死锁问题,因为锁已释放。

Java 中怎么防止在线程阻塞与唤醒时死锁

 LockSupport 优势

LockSupport类为线程阻塞唤醒提供了基础,同时,在竞争条件问题上具有wait和notify无可比拟的优势。使用wait和notify组合时,某一线程在被另一线程notify之前必须要保证此线程已经执行到wait等待点,错过notify则可能永远都在等待,另外notify也不能保证唤醒指定的某线程。反观LockSupport,由于park与unpark引入了许可机制,许可逻辑为:  

根据这两个逻辑,对于同一条线程,park与unpark先后操作的顺序似乎并不影响程序正确地执行。假如先执行unpark操作,许可则为1,之后再执行park操作,此时因为许可等于1直接返回往下执行,并不执行阻塞操作。 最后,LockSupport的park与unpark组合真正解耦了线程之间的同步,不再需要另外的对象变量存储状态,并且也不需要考虑同步锁,wait与notify要保证必须有锁才能执行,而且执行notify操作释放锁后还要将当前线程扔进该对象锁的等待队列,LockSupport则完全不用考虑对象、锁、等待队列等问题。

上述内容就是Java 中怎么防止在线程阻塞与唤醒时死锁,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注亿速云行业资讯频道。

推荐阅读:
  1. Java常见的多线程面试题和解题思路
  2. 关于Java的并发编程

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java

上一篇:HTML5本地存储之IndexedDB有什么用

下一篇:在Linux系统中的时间转化方法

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》