java中的锁
Posted andywu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java中的锁相关的知识,希望对你有一定的参考价值。
和上面的类似,不激烈情况下,性能比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();//@1 if (!cacheValid) { // Must release read lock before acquiring write lock rwl.readLock().unlock();//@4 rwl.writeLock().lock();//@2 // Recheck state because another thread might have acquired // write lock and changed state before we did. if (!cacheValid) {//@3 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行,当有线程正在对数据进行 写操作的时候,运行到@1行的线程要等待 写操作的完成,因为第一个运行到@2的线程会加上锁,然后对数据进行需该,期间不允许任何线程进行读或者是写的操作,
当写完后,在该线程上加上读锁操作,以防止解写锁后,别的线程对数据再次进行写时出错.在第一个运行到@2的线程之后的很多线程,
可能已经运行到了@4,当对数据修改好之后,解除掉写锁,别的线程就会执行到@2,这时第一个线程已经经数据修改好了,所以有了@3的判断。
在编写多线程程序的时候,要置于并发线程的环境下考虑,巧妙的运用ReentrantReadWriteLock,在运用时,注意锁的降级,写入锁可以获得读锁,读锁不可以获得写入锁,所以在上写入锁时,必须先将读锁进行解除,然后上读锁。
使用时注意的几个方面:
读锁是排写锁操作的,读锁不排读锁操作,多个读锁可以并发不阻塞。即在读锁获取后和读锁释放之前,写锁并不能被任何线程获得,
多个读锁同时作用期间,试图获取写锁的线程都处于等待状态,当最后一个读锁释放后,试图获取写锁的线程才有机会获取写锁。
写锁是排写锁、排读锁操作的。当一个线程获取到写锁之后,试图获取写锁和读锁的其他线程都处于等待状态,直到写锁被释放(同一个线程在获取写锁后是可以继续获得读锁的)。即:
rwl.writeLock().lock();
//在写锁状态中,可以获取读锁
rwl.readLock().lock();
rwl.writeLock().unlock();
读锁是不能够获得写锁的,如果要加写锁,本线程必须释放所持有的读锁,即:
rwl.readLock().lock();
//......
//必须释放掉读锁,才能够加写锁
rwl.readLock().unlock();
rwl.writeLock().lock();
以上是关于java中的锁的主要内容,如果未能解决你的问题,请参考以下文章