@boothsun
2017-08-11T13:18:13.000000Z
字数 1900
阅读 1362
Java多线程
Java接口Lock有三个实现类:ReentrantLock、ReentrantReadWriteLock.ReadLock和ReentrantReadWriteLock.WriteLock。Lock接口提供了比使用synchronized更广泛的锁操作。
ReentrantLock是一个可重入的互斥锁。重入的含义是:当某个线程请求一个由其他线程持有的锁时,发出请求的线程就会被阻塞。但是如果某个线程试图获得一个已经由它自己持有的锁时,这个请求是会成功的。"重入"意味着获取锁的操作的粒度是"线程",而不是"调用"。重入的一种实现方式就是,为每个锁关联一个获取计数值和一个所有者线程。当计数值为0时,这个锁就被认为是没有被任何线程持有。当线程请求一个未被持有的锁时,JVM将记下锁的持有者,并且将获取到的计数值置为1.如果同一个线程再次获取这个锁,计数值将被递增,而当线程退出同步代码块时,计数器会相应地递减。当计数值为0时,这个锁将被释放。
对于ReentrantLock锁将由最近成功获得锁,并且没有释放该锁的线程所拥有。当锁没有被另外一个线程所拥有时,调用lock的线程将会成功获取该锁并返回。如果当前线程已经拥有该锁,此方法将立即返回。
lock()
获取锁
加锁,如果该锁没有被另一个线程保持,则获取该锁并立即返回,将锁的保持计数设置为1。
如果当前线程之前已经获取到了该锁,则将保持计数加1,并且该方法立即返回。
如果该锁已经被另一个线程保持,则该线程不可被调度(即当前线程处于阻塞状态)直到该线程获取到锁,并且在获取到锁后,将保持计数设置为1。
unlock
释放锁
试图释放锁。如果当前线程是此锁所有者,则将保持计数减1。如果保持计数器现在为0,则释放该属锁。如果当前线程不是此锁的持有者,则抛出IllegalMonitorStateException。
private Lock lock = new ReentrantLock() ;
public void await() {
try {
lock.lock();//加锁
} finally {
lock.unlock();//释放锁
}
}
trylock()
仅在调用时锁未被另一个线程保持的情况下,才获取锁。
如果该锁没有被另一个线程保持,并且立即返回 true 值,则将锁的保持计数设置为 1。即使已将此锁设置为使用公平排序策略,但是调用 tryLock() 仍将 立即获取锁(如果有可用的),而不管其他线程当前是否正在等待该锁。在某些情况下,此“闯入”行为可能很有用,即使它会打破公平性也如此。如果希望遵守此锁的公平设置,则使用 tryLock(0, TimeUnit.SECONDS) ,它几乎是等效的(也检测中断)。
如果当前线程已经保持此锁,则将保持计数加 1,该方法将返回 true。
如果锁被另一个线程保持,则此方法将立即返回 false 值。
tryLock(long timeout, TimeUnit unit)
如果锁在给定等待时间内没有被另一个线程保持,且当前线程未被中断,则获取该锁。
为了使用公平的排序策略,如果其他线程已经获取此锁,并且还有其他线程都在等待该锁,则立刻不会获取一个可用的锁,而公平的和其他线程进行等待锁分配。这与trylock方法相反。如果想使用一个允许闯入公平锁的定时tryLock,那么可以将定时形式和不定时形式组合在一起使用:
if(lock.tryLock() || lock.tryLock(timeout,uniy)) {
//.....
}