总结:Java锁机制

二、  Lock

lock()方法:获取锁,被占用则等待,直到等到为止,即阻塞式获取;

lock.lockInterruptibly()方法:类似lock(),唯一不同的是,这个获取(阻塞)过程可以代码去中断的,即假设B线程在等待A线程的锁,B线程可以通过调用interrupt()方法中断自己的等待。注意:只能中断阻塞线程,不会中断执行中的线程更确切 的说,如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞, 那么,它将接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态。

tryLock():非阻塞式获取,即获取不到不会等待,立即返回失败

tryLock(long time, TimeUnit unit):非阻塞式获取,即获取不到,则会等待unit时间,如果还未获取到,则返回失败。

newCondition(): 返回一个绑定到lock对象上的condition对象,作用是处理一些条件下的问题,如边界问题(如数组满则不能put,数组空则不能take等) 

 

ReentrantLock,即 可重入锁。ReentrantLock是唯一实现了Lock接口的类,并且ReentrantLock提供了更多的方法。

参考:

Lock的lockInterruptibly()方法

Lock中为什么要使用多个Condition

三、  ReadWriteLock

自定义

四、  synchronized 与 Lock

Lock提供了比synchronized更多的功能。但是要注意以下几点:

    1)synchronized是Java语言的关键字,因此是内置特性,Lock不是Java语言内置的,Lock是一个接口,通过实现类可以实现同步访问。

    2)synchronized是在JVM层面上实现的,不但可以通过一些监控工具监控synchronized的锁定,而且在代码执行时出现异常,JVM会自动释放锁定,但是使用Lock则不行,lock是通过代码实现的,要保证锁定一定会被释放,就必须将unLock()放到finally{}中

    3)在资源竞争不是很激烈的情况下,Synchronized的性能要优于ReetrantLock,但是在资源竞争很激烈的情况下,Synchronized的性能会下降几十倍,但是ReetrantLock的性能能维持常态。

参考:

java 锁 Lock接口详解

Synchronized与ReentrantLock区别总结(简单粗暴,一目了然)

五、可重入锁与不可重入锁

可重入锁, 即一个线程可以进入任何一个 该线程 已经拥有的锁所同步着的代码块 。

参考: https://www.cnblogs.com/xdyixia/p/9383388.html

六、关于公平锁和非公平锁

公平锁:首先判断当前AQS的state是否等于0,锁是否被占用,如果没有被占用的话,继续判断队列中是否有排在前面的线程在等待锁,没有的话就修改statte状态
然后将当前线程记录为独占锁的线程,继续判断当前线程是否为独断锁的线程,ReentrantLock是可冲入的,线程可以不停地Lock来增加state的值,对应的需要unlock来解锁,减少state的值
如果上面的条件判断失败,即获取锁失败,则将线程加入到等待线程队列队尾,然后阻塞线程,等待被唤醒

 

非公平锁:非公平锁逻辑基本跟公平锁一致,最本质的区别是,当当前的锁状态没有被占用时,当前线程可以直接占用,而不需要判断当前队列中是否有等待线程。

参考:

关于公平锁和非公平锁

七、CAS与AQS