必须在 finally 将锁释放掉,否则将会引起死锁
有时间限制的同步,
可以被Interrupt的同步(
synchronized的同步是不能Interrupt的)。
和上面的类似,不激烈情况下,性能比synchronized略逊,而激烈的时候,也能维持常态。激烈的时候,Atomic的性能会优于ReentrantLock一倍左右。
Lock lock = new ReentrantLock(); lock.lock(); try { }
finally { lock.unlock(); }
一下示例为 java api并发库中 ReentrantReadWriteLock自带的实例,下面进行解读
class CachedData { Object data; volatile boolean cacheValid; ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); void processCachedData() { rwl.readLock().lock();[email protected] if (!cacheValid) { // Must release read lock before acquiring write lock rwl.readLock().unlock();[email protected] rwl.writeLock().lock();[email protected] // Recheck state because another thread might have acquired // write lock and changed state before we did. if (!cacheValid) [email protected] data = ... cacheValid = true; } // Downgrade by acquiring read lock before releasing write lock rwl.readLock().lock(); rwl.writeLock().unlock(); // Unlock write, still hold read } use(data); rwl.readLock().unlock(); } }
//当有n多线程 使用同一CachedData 实例对象 调用processCachedData方法时,就会产生线程的并发问题.
@1行,当有线程正在对数据进行 写操作的时候,[email protected] 写操作的完成,[email protected],然后对数据进行需该,期间不允许任何线程进行读或者是写的操作,
当写完后,在该线程上加上读锁操作,以防止解写锁后,别的线程对数据再次进行写时出错.在第一个运行到@2的线程之后的很多线程,
[email protected],当对数据修改好之后,解除掉写锁,[email protected],这时第一个线程已经经数据修改好了,[email protected]
在编写多线程程序的时候,要置于并发线程的环境下考虑,巧妙的运用ReentrantReadWriteLock,在运用时,注意锁的降级,写入锁可以获得读锁,读锁不可以获得写入锁,所以在上写入锁时,必须先将读锁进行解除,然后上读锁。
使用时注意的几个方面:
读锁是排写锁操作的,读锁不排读锁操作,多个读锁可以并发不阻塞。即在读锁获取后和读锁释放之前,写锁并不能被任何线程获得,
多个读锁同时作用期间,试图获取写锁的线程都处于等待状态,当最后一个读锁释放后,试图获取写锁的线程才有机会获取写锁。
写锁是排写锁、排读锁操作的。当一个线程获取到写锁之后,试图获取写锁和读锁的其他线程都处于等待状态,直到写锁被释放(同一个线程在获取写锁后是可以继续获得读锁的)。即:
rwl.writeLock().lock();
//在写锁状态中,可以获取读锁
rwl.readLock().lock();
rwl.writeLock().unlock();
读锁是不能够获得写锁的,如果要加写锁,本线程必须释放所持有的读锁,即:
rwl.readLock().lock();
//……
//必须释放掉读锁,才能够加写锁
rwl.readLock().unlock();
rwl.writeLock().lock();
原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/16923.html