Java_并发线程_Lock、ReadWriteLock

来源:互联网 发布:mac lnmp一键安装包 编辑:程序博客网 时间:2024/05/17 22:50

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 lockfinally {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()

参考Java_并发线程_Condition一文

(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 lockrwl.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 lockrwl.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();

0 0