Java_并发线程_Lock、ReadWriteLock
1.Lock
ReentrantLock是Lock接口的实现类,使用Lock应该接合线程来使用。如果lock锁没有被其它的线程占用,则当前线程可以立即获得lock锁。同一个线程可在lock锁未释放之前,调用lock多次,使用getHoldCount()得到当前线程lock锁的次数。isHeldByCurrentThread()则判断当前线程是否拥有lock锁。
(1).使用格式
一定要在finally中调用lock.unlock()解锁,防止死锁。Lock l = ...; l.lock(); try { // access the resource protected by this lock finally { l.unlock(); }}
(2).常用方法
1).void lock();
尝试获得lock锁,如果锁被别的线程持有,则当前线程不在执行,也不能被调度,直到拿到锁为止;
2).void lockInterruptibly() throws InterruptedException
尝试获取锁,如果锁可以获取,那么立刻返回。如果无非获取锁,那么线程停止执行,并且不能被再调度,直到当前线程被interrupt,则抛出异常;
3).boolean tryLock()
尝试获得锁,如果成功那么锁住对象然后返回true,否则返回false,这个方法会立即返回;
4).boolean tryLock(long time, TimeUnit unit) throws InterruptedException
tryLock类似,等待最大时间内试图获得锁;
5).unlock()
释放锁,减一
6).newCondition()
(3).与synchronized的区别
synchronized锁的释放是语言内置的,不会出现忘记释放锁的情况,另外由于是语言内置的支持,调试是能很快知道锁被哪个线程持有,它加锁的次数。而Lock只是一个普通的类,所以调试器并不知道这个锁的任何信息,它只是一个普通的对象(当然你可以仔细观察每个线程的stack frame来看它在等待锁),但是Lock更加的灵活具有扩展性。
所以建议:如果只是为了实现互斥,那么使用synchronized,如果想用Lock附加的功能,那么才使用Lock。
2.ReadWriteLock
ReentrantReadWriteLock是ReadWriteLock接口的实现类,接合线程使用。
(1).读锁和写锁条件
1).不同一线程
读锁不互斥,读锁与写锁互斥,写锁与写锁互斥。
2).同一线程
读锁可以获得多次getReadHoldCount(),写锁可以获得多次getWriteHoldCount;
读锁下不能获得写锁,但是写锁下可以提前获得读锁。
(2).格式
class CachedData { Object data; volatile boolean cacheValid; final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); void processCachedData() { rwl.readLock().lock(); if (!cacheValid) { // Must release read lock before acquiring write lock rwl.readLock().unlock(); rwl.writeLock().lock(); try { // Recheck state because another thread might have // acquired write lock and changed state before we did. if (!cacheValid) { // data = ... cacheValid = true; // Downgrade by acquiring read lock before releasing // write lock rwl.readLock().lock(); } } finally { rwl.writeLock().unlock(); // Unlock write, still hold read } } try { // use(data); } finally { rwl.readLock().unlock(); } } }
(3).使用注意
读锁是排写锁操作的,读锁不排读锁操作,多个读锁可以并发不阻塞。即在读锁获取后和读锁释放之前,写锁并不能被任何线程获得,
多个读锁同时作用期间,试图获取写锁的线程都处于等待状态,当最后一个读锁释放后,试图获取写锁的线程才有机会获取写锁。
写锁是排写锁、排读锁操作的。当一个线程获取到写锁之后,其他试图获取写锁和试图获取读锁的线程都处于等待状态,直到写锁被释放。
写锁是可以获得读锁的,即:
rwl.writeLock().lock(); //在写锁状态中,可以获取读锁 rwl.readLock().lock(); rwl.writeLock().unlock();读锁是不能够获得写锁的,如果要加写锁,本线程必须释放所持有的读锁,即:
rwl.readLock().lock(); //...... //必须释放掉读锁,才能够加写锁 rwl.readLock().unlock(); rwl.writeLock().lock();
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。