synchronized和ReentrantLock

 

相同之处

都是阻塞式的同步,也就是说当如果一个线程获得了对象锁,进入了同步块,其他访问该同步块的线程都必须阻塞在同步块外面等待,而进行线程阻塞和唤醒的代价是比较高的(操作系统需要在用户态与内核态之间来回切换,代价很高,不过可以通过对锁优化进行改善)。

 

不同之处

 

实现层次

这两种方式最大区别就是对于Synchronized来说,它是java语言的关键字,是原生语法层面的互斥,需要jvm实现。而ReentrantLock它是JDK 1.5之后提供的API层面的互斥锁,需要lock()和unlock()方法配合try/finally语句块来完成。

 

锁的获取

synchronized:假设A线程获得锁,B线程等待。如果A线程阻塞,B线程会一直等待。

ReentrantLock 获取锁的方式更加灵活
    a)  lock(), 如果获取了锁立即返回,如果别的线程持有锁,当前线程则一直处于休眠状态,直到获取锁。

    b) tryLock(), 如果获取了锁立即返回true,如果别的线程正持有锁,立即返回false。

    c)tryLock(long timeout,TimeUnit unit),   如果获取了锁定立即返回true,如果别的线程正持有锁,会等待参数给定的时间,在等待的过程中,如果获取了锁,就返回true,如果等待超时,返回false。

    d) lockInterruptibly:如果获取了锁立即返回,如果没有获取锁,当前线程处于休眠状态,直到或者获取锁,或者当前线程被别的线程中断。

 

锁的释放

synchronized:自动释放锁,同步块代码执行完毕或出现异常。

ReentrantLock :finally块中释放锁

 

相比于synchronized,ReentrantLock增加了一些高级功能。

等待可中断

等待可中断是指持有锁的线程长期不释放的时候,正在等待的线程可以选择放弃等待,改为处理其他事情。

 

公平锁

公平锁是指多个线程在等待同一个锁时,必须按照申请锁的时间顺序获得锁。非公平锁无法保证这一点,在锁被释放时,任何一个等待的线程都有机会获得锁。

synchronized中的锁是非公平锁,ReentrantLock默认是非公平锁,可以通过构造函数的布尔参数设为公平锁。

 

绑定多个条件

一个ReentrantLock对象可以同时绑定多个Condition对象,而在synchronized中,锁对象的wait()和notify()或notifyAll()方法可以实现一个隐含的条件,如果要和多余一个条件关联的时候,就不得不额外地添加一个锁,而ReentrantLock则无须这么做,只需要多次调用new Condition()方法即可。

 

 

 

总结如下

类别

synchronized

Lock

存在层次

Java的关键字,在jvm层面上

是一个类,API层面

锁的释放

执行完同步块代码,释放锁

执行同步块代码发生异常,释放锁

在finally中释放锁

锁的获取

假设A线程获得锁,B线程等待。

如果A线程阻塞,B线程会一直等待

Lock有多个锁获取的方式

锁状态

无法判断

可以判断

锁类型

可重入 不可中断 非公平

可重入 可中断 可公平

posted on 2018-08-31 16:01  Deltadeblog  阅读(187)  评论(0编辑  收藏  举报

导航