lock.lock和synchronized(lock),lock比synchronized灵活吗

  lock.lock和synchronized(lock),lock比synchronized灵活吗

  什么是LockSupper?他跟锁定和同步化有什么关系?解决什么?_ 51c to Blog _ lock和synchronized有什么区别?

  什么是LockSupper?他跟锁定和同步化有什么关系?解决什么?

  话不多说,先贴文档:

  关键词:创建线程和其他同步类的基本线程阻塞原语;

  简单来说就是阻塞线程;但是阻塞线程的时候不能用await和wail吗?

  请看第三行:方法park和unpark提供了阻塞和解锁(唤醒)线程的有效方法。这种方法不会遇到现在不推荐使用的方法Thread.suspend和Thread.resume无法使用的问题:调用park的一个线程和另一个线程之间的尝试因为许可证的原因保持unpark活动。另外,如果调用者线程中断,park会返回,支持超时版本。Park方法也可以在其他任何时候返回,因为“没有原因”,所以一般必须在返回前重新检查条件的循环中调用。从这个意义上说,park作为一个“忙着等待”的优化,并不浪费时间选择,只有在必须与unpark配对时才有效。

  有点混乱,但是我明白了一些东西,就是解决了一些不建议使用的情况。然后,支持多线程调用和超时。

  要理解LockSupport函数的前提,首先要分析一下原来的synchronized;锁盒1:

  对于这个印刷顺序,我想大家应该都很了解。两个线程同时按顺序执行。因为我们添加了synchronized的同步锁,保证了锁对象相同,那么按照代码块的顺序,基本上线程1先获得cpu时间片。当线程1执行休眠对象时,线程将被挂起,即被阻塞,同时锁对象将被释放。就像线程2的锁对象和线程1的锁对象一样,那么线程2进入同步锁,开始执行唤醒动作。被唤醒的对象恰好是线程1挂起的对象,所以当线程1被唤醒后,继续执行下一个动作。

  所以这里要注意:原则上只要两个线程同时用synchronized同步锁,并且锁对象是同一个对象,那么当线程被阻塞时,锁就会被释放,不会死锁。

  其实跟sync的底层实现有关系,因为它的底层实现里有一个阻塞双向链表。并将控制一个对象的当前被占用的线程实例。因此,当当前被占用的线程被阻塞时,锁将被释放。

  注意,我们在执行线程阻塞(wait方法)的时候,一定要用synchronized来修饰代码块,这也是jvm的要求,因为jvm在执行锁休眠的时候,会释放锁,所以我们要想释放它,就要先获取锁,也就是先获取synchronized锁,锁的对象必须和我们唤醒和阻塞的对象是同一个对象。

  如果在不使用锁的情况下直接执行线程的wait/notify方法,将会引发异常IllegalMonitorStateException。比如下图;并且会出现死锁;

  案例二:

  如果线程1稍后执行,线程2执行,会发生什么?即先被执行唤醒,再被执行封锁休眠;

  结果唤醒线程执行成功,但随后执行线程1的阻塞操作,执行完成后一直阻塞,无法唤醒。

  通俗的理解就是,当一个人把一个垃圾桶里的垃圾清理掉,然后另一个人把另一个垃圾扔进垃圾桶,那么垃圾桶里就一直有一个垃圾;对于第一个人,他以为自己清理了垃圾桶;至于第二个人,他一直在等第一个人清理垃圾桶。继续等。

  问题是不会有逻辑错误,只有死锁。

  案例三:

  我们都知道lock,所以让我们试着将案例2中的lock对象改为Lock中的condition对象,看看这个对象中的await()/signal()方法是如何工作的。

  同样的僵局也发生过,情况也一样。

  案例4:

  我们知道Object对象的wait/notify方法必须与synchronized一起使用,所以让我们也试试condition是否也需要与lock一起使用?

  是的,错误都是一样的。我们需要屏蔽/唤醒一个对象,我们都需要获得锁,才能操作对象的屏蔽和唤醒。这些都是基于jvm底层法规的要求。

  对于以上四种情况,我们可以从执行的结果中得出一些结论:

  阻塞和唤起锁的前提条件必须和锁一起使用,锁对象和代码块中的对象必须相同。线程的阻塞和唤醒必须顺序执行,否则可能会发生死锁。那么这也是传统锁的缺点。然后我们的新锁对象就来了。锁定支持

  所以只看源代码?

  没有构造,这是一个工具类。

  继续:

  你大概可以看到这个工具类的所有方法,那么它们是什么意思呢?我们来解读一下;

  Public static void park()禁止当前线程进行线程调度,除非有许可证可用。

  如果许可证可用,则它被消费,调用立即返回;否则,出于线程调度的目的,当前线程将被禁用,并将处于休眠状态,直到发生以下三种情况之一:

  其他一些线程调用当前线程作为目标解包;

  或者一些其他线程的当前线程中断;

  要么电话是假的(就是无理由)要退。

  此方法不报告哪个线程导致该方法返回。调用方应该首先重新检查导致线程停止的条件。调用者还可以确定线程返回时的中断状态。

  从上面官方的描述中,我们可以抓住一个关键词:牌照。

  也就是说,LockSupport类使用了一个叫做Permit的概念,通过它来实现阻塞和唤起线程的功能。对于每个线程,将有一个许可证,它有两种状态,0,1;默认情况下为0;

  众所周知,我们在PV操作中有一个概念叫信号量,可以实现多线程环境下的线程唤醒和线程阻塞。那么这个许可证和这个信号量概念非常相似,只不过信号值是无限的,但是许可证只会有0,1。

  当我们的线程1调用park()方法时,当前线程会被阻塞挂起,然后等待其他线程将其license设置为1,然后该线程被唤醒,然后将其license设置为0,再执行下面的逻辑。

  public staticvodunpark(thread thread)禁用当前线程进行线程调度,直到指定的截止日期,除非许可证可用。

  如果许可证可用,则它被消费,调用立即返回;否则,出于线程调度的目的,当前线程将被禁用,并将处于休眠状态,直到发生以下四种情况之一:

  其他一些线程调用当前线程作为目标解包;或者

  其他线程当前是中断;或者

  超过了指定的时间限制;或者

  假的(也就是说没理由)回电。

  此方法不报告哪个线程导致该方法返回。调用方应该首先重新检查导致线程停止的条件。调用者还可以确定线程的中断状态或返回当前时间。

  如果线程被park阻塞,调用它将解除阻塞。但是如果给定的线程没有被阻塞,那么什么也不做。因为当一个线程的license是1的时候,如果你再唤醒它,它就是1了。

  这样有什么好处?也就是说他可以无脑调用唤醒线程,而不是唤醒被阻塞的线程。

  看源代码。非常简单明了。它只是一个调用UNSAFE类中的unpark(thread)的主代码。不安全就不说了。一类局部方法在较低层实现。基本上可以认为是原子操作。

  LockSupport的其他方法就不解释了,基本都是重载;

  案例5:

  然后,让我们使用上面案例2和案例3中的方法,看看是否会抛出异常。

  结果显而易见。虽然线程2先对线程1执行了unpark()操作,也就是唤起操作,但是3秒后线程1执行了阻塞操作。当线程1执行park()操作时,立即被唤醒。

  我们可以知道,改变是由线程的许可证控制的:第一步,线程2将线程1的许可证从默认值0改变为1,然后线程1进行阻塞操作。当它发现自己线程的license是1时,它会直接唤醒,然后把自己线程的license改成0,然后继续执行后续动作。

  注意:这里我们没有加锁。

  有趣的扩展1:

  信号量的特点我们都知道,所以上面也提到了许可证的特点,我们来试试。假设,先激发一次,再屏蔽两次,看看结果是什么?

  结果很明显有堵。原因是当它第一次被唤醒时,它的许可证被初始化为0。然后,当第二次执行阻塞时,就真的阻塞了。

  有趣的扩展2:

  所以我们继续展开1。如果我们两次唤醒它,然后两次阻断它呢?

  结果充分证明许可证只能是1或0;第一次唤醒时,我们将许可证设置为1,然后第二次唤醒时,我们只能将其设置为1;然后在第一个街区,把1改成0,在第二个街区,0就不能唤起了。所以第二次堵塞已经被堵住了。

  有趣的扩展3:

  反复唤醒,反复阻断,但我们必须阻断它。如何实现?尝试以下方法?

  诶!不堵。这是怎么回事?欢迎大家分析一下,休眠2是怎么被唤醒的?执照变更的顺序是什么?

  请留言分享你的分析。

  总结:

  LockSupport解决了阻塞和唤醒序列的问题,解决方案是通过许可证的概念。但是有一个规定,许可证只能是1,0;而且两种状态转换都有一定的规律,规律如上例所示;

  为什么要醒两次?挡了两次就被挡了,无法唤起。因为连续调用两次unPark()方法本质上就是反复将license设置为1,那么调用两次Park()方法就意味着将1设置为0。唤醒的前提条件是当前许可必须是1,第一次阻塞唤醒操作会将1变为0,所以当前线程的许可已经是0,不能被唤醒;

  LockSupport是通过本地方法实现的,用C实现,基本可以理解为原子操作。

  Lock是一个工具类,因为私有化的构造方法和内部方法都是静态方法。

  Lock不需要使用lock,只需要唤醒和阻塞线程即可。

  版权归作者所有:原创作品来自博主changemax,转载请联系作者取得转载授权,否则将追究法律责任。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: