在java中的锁分为以下(其实就是按照锁的特性和设计来划分):
1、公平锁/非公平锁
2、可重入锁
3、独享锁/共享锁
4、互斥锁/读写锁
5、乐观锁/悲观锁
6、分段锁
7、偏向锁/轻量级锁/重量级锁
8、自旋锁(java.util.concurrent包下的几乎都是利用锁)
从底层角度看常见的锁也就两种:Synchronized和Lock接口以及ReadWriteLock接口(读写锁)
从类关系看出Lock接口是jdk5后新添的来实现锁的功能,其实现类:ReentrantLock、WriteLock、ReadLock。
其实还有一个接口ReadWriteLock,读写锁(读读共享、读写独享、写读独享、写写独享)。
Lock接口与synchronized关键字本质上都是实现同步功能。
区别:ReentrantLock:使用上需要显示的获取锁和释放锁,提高可操作性、可中断的获取获取锁以及可超时的获取锁,默认是 非公平的但可以实现公平锁,悲观,独享,互斥,可重入,重量级锁。
ReentrantReadWriteLock:默认非公平但可实现公平的
,悲观,写独享,读共享,读写,可重入,重量级锁。
synchronized:关键字,隐式的获取锁和释放锁,不具备可中断、可超时,非公平、互斥、悲观、独享、可重入的重量级
Lock的使用也很简单:
Lock lock = new ReentrantLock();
lock.lock();
try{
}finally{
lock.unlock();
}
//注意:不要将lock方法写在try块中,因为如果在获取锁的时候发生异常,异常抛出的同时也会导致锁无故的释
//放 否则会程序会报监视状态异常
Exception in thread "线程一" java.lang.IllegalMonitorStateException
at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:155)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1260)
at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:460)
//ReentrantLock必须要在finally中unlock(), 否则,如果在被加锁的代码中抛出了异常,那么这个锁将会永远无法释放.
//synchronized就没有这样的问题, 遇到异常退出时,会释放掉已经获得的锁.
Lock接口提供的 ,synchronized关键字所不具备的特性
特性 | 描述 |
尝试性非阻塞地获取锁(tryLock方法) |