首页编程java编程java 什么是可重入锁(java 可重入锁如何避免死锁的)

java 什么是可重入锁(java 可重入锁如何避免死锁的)

编程之家2023-10-1295次浏览

老铁们,大家好,相信还有很多朋友对于java 什么是可重入锁和java 可重入锁如何避免死锁的的相关问题不太懂,没关系,今天就由我来为大家分享分享java 什么是可重入锁以及java 可重入锁如何避免死锁的的问题,文章篇幅可能偏长,希望可以帮助到大家,下面一起来看看吧!

java 什么是可重入锁(java 可重入锁如何避免死锁的)

java 可重入锁如何避免死锁的

synchronized标记的同步是要绑定一个对象的,不写的话实际上实际上就是synchronized(this),即绑定当前对象,这个this对象就是锁(synchronized中可以认为就是监视器),当LoggingWidget执行dosomething的时候获得了这把锁(this),那么他去调用父类(Widget)的dosomthing的时候,父类的dosomething方法也要得到这个锁(this),但是子类的这个方法还没有运行完毕,所以还持有这个锁,父类方法在等,子类不释放锁还拼命的让父类方法执行,却不知道父类方法在眼巴巴的等着这个锁,这样就死锁了······

java的可重入锁用在哪些场合

用在只能单线程处理的地方呗,一般来说,如果一个方法被多个线程调用,方法里有修改类变量就需要锁了,因为在线程运行时,类变量被拷贝到线程专用的缓存,然后再拷贝回程序内存,如果同时有多个线程做上述动作,最后一个线程改变后的值就会覆盖其他线程做的修改。

java 哪个锁是非重入的

读写锁 ReadWriteLock读写锁维护了一对相关的锁,一个用于只读操作,一个用于写入操作。只要没有writer,读取锁可以由多个reader线程同时保持。写入锁是独占的。

java 什么是可重入锁(java 可重入锁如何避免死锁的)

互斥锁一次只允许一个线程访问共享数据,哪怕进行的是只读操作;读写锁允许对共享数据进行更高级别的并发访问:对于写操作,一次只有一个线程(write线程)可以修改共享数据,对于读操作,允许任意数量的线程同时进行读取。

与互斥锁相比,使用读写锁能否提升性能则取决于读写操作期间读取数据相对于修改数据的频率,以及数据的争用——即在同一时间试图对该数据执行读取或写入操作的线程数。

读写锁适用于读多写少的情况。

java 什么是可重入锁(java 可重入锁如何避免死锁的)

可重入读写锁 ReentrantReadWriteLock

属性ReentrantReadWriteLock也是基于 AbstractQueuedSynchronizer实现的,它具有下面这些属性(来自Java doc文档):

*获取顺序:此类不会将读取者优先或写入者优先强加给锁访问的排序。

*非公平模式(默认):连续竞争的非公平锁可能无限期地推迟一个或多个reader或writer线程,但吞吐量通常要高于公平锁。

*公平模式:线程利用一个近似到达顺序的策略来争夺进入。当释放当前保持的锁时,可以为等待时间最长的单个writer线程分配写入锁,如果有一组等待时间大于所有正在等待的writer线程的reader,将为该组分配读者锁。

*试图获得公平写入锁的非重入的线程将会阻塞,除非读取锁和写入锁都自由(这意味着没有等待线程)。

*重入:此锁允许reader和writer按照 ReentrantLock的样式重新获取读取锁或写入锁。在写入线程保持的所有写入锁都已经释放后,才允许重入reader使用读取锁。

writer可以获取读取锁,但reader不能获取写入锁。

*锁降级:重入还允许从写入锁降级为读取锁,实现方式是:先获取写入锁,然后获取读取锁,最后释放写入锁。但是,从读取锁升级到写入锁是不可能的。

*锁获取的中断:读取锁和写入锁都支持锁获取期间的中断。

* Condition支持:写入锁提供了一个 Condition实现,对于写入锁来说,该实现的行为与 ReentrantLock.newCondition()提供的Condition实现对 ReentrantLock所做的行为相同。当然,此 Condition只能用于写入锁。

读取锁不支持 Condition,readLock().newCondition()会抛出 UnsupportedOperationException。

*监测:此类支持一些确定是读取锁还是写入锁的方法。这些方法设计用于监视系统状态,而不是同步控制。

实现AQS回顾在之前的文章已经提到,AQS以单个 int类型的原子变量来表示其状态,定义了4个抽象方法( tryAcquire(int)、tryRelease(int)、tryAcquireShared(int)、tryReleaseShared(int),前两个方法用于独占/排他模式,后两个用于共享模式)留给子类实现,用于自定义同步器的行为以实现特定的功能。

对于 ReentrantLock,它是可重入的独占锁,内部的 Sync类实现了 tryAcquire(int)、tryRelease(int)方法,并用状态的值来表示重入次数,加锁或重入锁时状态加 1,释放锁时状态减 1,状态值等于 0表示锁空闲。

对于 CountDownLatch,它是一个关卡,在条件满足前阻塞所有等待线程,条件满足后允许所有线程通过。内部类 Sync把状态初始化为大于 0的某个值,当状态大于 0时所有wait线程阻塞,每调用一次 countDown方法就把状态值减 1,减为 0时允许所有线程通过。利用了AQS的共享模式。

现在,要用AQS来实现 ReentrantReadWriteLock。

一点思考问题

* AQS只有一个状态,那么如何表示多个读锁与单个写锁呢?

* ReentrantLock里,状态值表示重入计数,现在如何在AQS里表示每个读锁、写锁的重入次数呢?

*如何实现读锁、写锁的公平性呢?

java如何实现线程安全,synchronized和lock的区别,可重入锁

一、synchronized和lock的用法区别

synchronized:在需要同步的对象中加入此控制,synchronized在方法上,也在特定代码块中,括号中表示需要锁的对象。

lock:需要显示指定起始位置和终止位置。一般使用ReentrantLock类做为锁,多个线程中必须要使用一个ReentrantLock类做为对象才能保证锁的生效。且在加锁和解锁处需要通过lock()和unlock()显示指出。所以一般会在finally块中写unlock()以防死锁。

二、synchronized和lock用途区别

synchronized原语和ReentrantLock在一般情况下没有什么区别,但是在非常复杂的同步应用中,请考虑使用ReentrantLock,特别是遇到下面2种需求的时候。

某个线程在等待一个锁的控制权的这段时间需要中断

2.需要分开处理一些wait-notify,ReentrantLock里面的Condition应用,能够控制notify哪个线程

3.具有公平锁功能,每个到来的线程都将排队等候

END,本文到此结束,如果可以帮助到大家,还望关注本站哦!

java 什么是二级菜单栏(如何查看java虚拟机堆内存的参数值)java 栈和队列的区别是什么意思 JAVA中队列和栈的区别