Java线程获取-释放锁的抽象过程如图:

 

 

实际Java的线程启动,去获取锁(也就是通过CPU原子操作,设置线程的同步状态,可以去看下CAS算法和CPU cmpxchg指令)。得到锁,线程得以执行,得不到锁,线程进入同步队列(AbstractQueuedSynchronizer)。释放锁时,会让同步队列中的一个线程获得锁;非公平获取锁是从正要启动的线程或同步队列里获取一个线程。

 

lock:

synchronized 关键字:阻塞线程,隐式地自动获取/释放锁。        

                                                                                                                                                                       

ReentrantLock:其基本功能同synchronize相同,差别在于一是它比synchronize更灵活;再一个是ReentrantLock支持非公平获取锁;三是它使用CLH queue进行自旋,虽不阻塞线程,但却会占用CPU。

 

ReentrantReadWriteLock:跟ReentrantLock类似,支持非公平获取锁及不阻塞线程。所以个人认为它是对ReentrantLock的进一步优化,ReentrantReadWriteLock将锁拆分为读/写,支持锁的“降级”,读锁允许多个线程共享,而写锁是不允许。它用于对大集合的操作,且读操作远大于写操作的场景。

 

LockSupport:用于阻塞或唤醒线程的场景。

 

Condition: 用于实现等待/通知模式。

 

StampedLock:JDK1.8新加入的。它支持锁的“降级”和“升级”,它将锁拆分为了读,写,乐观读三种锁。它的写锁是排他锁,不允许重进入(每个锁,都有自己的version);读锁,是非排它锁;乐观读锁用于很小的只读取数据的代码片段,它通过tryOptimisticRead()放法获取锁,通过validate(long)方法验证锁期间,如果没有发生过写操作,返回true.这大大减少了锁竞争,提高了吞吐量。它同样用于对大集合的操作,且读操作远大于写操作的场景。

posted on 2017-08-07 15:36  seven-2017  阅读(74)  评论(0编辑  收藏  举报