synchronized与lock 对象锁、互斥锁、共享锁以及公平锁和非公平锁
synchronized与lock 都是用来实现线程同步的锁,synchronized对象锁,lock是一个接口,她的实现有reentrantlock互斥锁以及ReentrantReadWriteLock共享锁。
这里说明一下ReentrantReadWriteLock共享锁,所谓共享就是该锁提供读读锁共享,即可以多个线程共享一个读取锁,但是读写锁以及读读锁是互斥的。
看到网上有好多介绍介绍锁的种类的,有对象锁、互斥锁、共享锁以及公平锁和非公平锁,但是说明都不够详细了然,在这里用直白的说法记录一下,以供查阅,
对象锁:一般指的是synchronized这个锁,这个锁和对象有关,而且每个对象都会有个隐形的监视器,用于线程的同步,和这个对象线程交互的方法一般有wait和notify及notifyall,
调用wait方法,线程进入对象的监视器等待其他线程调用notify或notifyall,需要注意的是wait与notify或notifyall不能精确唤醒特定的线程,关于这个锁的用法,请参考这篇文章。
互斥锁:字面理解相互排斥的,即两个线程获得锁是互斥的,一个线程获得了锁,其他线程在此线程释放锁之前是不能获得锁的,java提供了一个互斥锁为reentrantlock,该锁是可以重入的
重入就是指,线程获得了锁之后,此线程可以进入任一其他方法中关于这个对象的锁。我们知道synchronized通过wait和notify等实现线程之间的交互,那么reentrantlock是通过
什么实现交互的呢,在这里就引入了api中一个重要的接口Condition,condition是什么呢,Condition
将 Object
监视器方法(wait
、notify
和 notifyAll
)分解成截然不同的对象,
以便通过将这些对象与任意 Lock
实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock
替代了 synchronized
方法和语句的使用,Condition
替代了 Object 监视
器方法的使用。这个是官网对condition的解释,可以看出来condition提供的功能和wait与notify是一样的,只不过condition用于lock中,而wait与notify是和synchronized一起使用
,这里需要说明的就是,condition提供的等待与唤醒机制,更明确指出wait哪一个线程,唤醒哪一个线程,关于Reentrantlock与condition的用法,请参考这篇文章
共享锁:共享锁前面已经讲过,就是多个线程可以共享锁,这里指的就是lock的实现类ReentrantReadWriteLock,ReentrantReadWriteLock分为读锁与写锁,这里锁的伟大之处就是,提供了读写锁分离
,分离的好处就是可以让读锁共享,就是多个线程可以共享读锁,读读共享以及写写互斥以及读写互斥,是这个锁的主要特点。下面是这个类的实现源码结构图:
上图有个AQS,这个是AbstractQueuedSynchronizer类的缩写,这个类是lock实现的重点,有兴趣的可以研究一下源码,Sync是AQS的实现,在ReentrantLock以及ReentrantReadWriteLock
类中,都有具体的实现,而FairSync和NonFairSync就是所谓的公平锁以及非公平锁