DK1.5以后,提供了读写锁ReentrantReadWriteLock,读写锁维护了一对锁:一个读锁,一个写锁。经过分离读锁和写锁,使得并发性相比通常的排他锁有了很大提高。在读多写少的状况下,读写锁可以提供比排他锁更好的并发性和吞吐量。java
/* * <p>This lock supports a maximum of 65535 recursive write locks * and 65535 read locks. Attempts to exceed these limits result in * {@link Error} throws from locking methods. * * @since 1.5 * @author Doug Lea */ public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable { private static final long serialVersionUID = -6992448646407690164L; /** Inner class providing readlock */ private final ReentrantReadWriteLock.ReadLock readerLock; /** Inner class providing writelock */ private final ReentrantReadWriteLock.WriteLock writerLock; /** Performs all synchronization mechanics */ final Sync sync; ... }
public class ReentrantReadWriteLockTest { ReentrantReadWriteLock lock; private ReentrantReadWriteLock.ReadLock readLock; private ReentrantReadWriteLock.WriteLock writeLock; private ReentrantReadWriteLockTest() { lock = new ReentrantReadWriteLock(); readLock = lock.readLock(); writeLock = lock.writeLock(); } public void read() { try { readLock.lock(); System.out.println(Thread.currentThread().getName() + " 开始读了。。。"); Thread.sleep(3000); }catch (InterruptedException e) { }finally { System.out.println(Thread.currentThread().getName() + " 读结束了。。。"); readLock.unlock(); } } public void write() { try { writeLock.lock(); System.out.println(Thread.currentThread().getName() + " 开始写了。。。"); Thread.sleep(3000); } catch (InterruptedException e) { } finally { System.out.println(Thread.currentThread().getName() + " 写完了。。。"); writeLock.unlock(); }
} }
测试1并发
public static void main(String[] args) { final ReentrantReadWriteLockTest test = new ReentrantReadWriteLockTest(); Thread t1 = new Thread(new Runnable() { @Override public void run() { test.read(); } }, "ReadThread1"); Thread t2 = new Thread(new Runnable() { @Override public void run() { test.read(); } }, "ReadThread2"); Thread t3 = new Thread(new Runnable() { @Override public void run() { test.write(); } }, "WriteThread1"); Thread t4 = new Thread(new Runnable() { @Override public void run() { test.write(); } }, "WriteThread4"); t1.start(); t2.start(); }
输出ide
ReadThread1 开始读了。。。 ReadThread2 开始读了。。。 ReadThread1 读结束了。。。 ReadThread2 读结束了。。。
结论:读读共享 测试
测试2spa
t2.start();
t3.start();
输出code
ReadThread2 开始读了。。。 ReadThread2 读结束了。。。 WriteThread1 开始写了。。。 WriteThread1 写完了。。。
结论:读写互斥orm
测试3blog
t4.start();
t3.start();
输出get
WriteThread4 开始写了。。。 WriteThread4 写完了。。。 WriteThread1 开始写了。。。 WriteThread1 写完了。。。
结论:写写互斥源码
注意:新生成变量时,要用final修饰
final ReentrantReadWriteLockTest test = new ReentrantReadWriteLockTest();
缘由:从内部类访问本地变量,本地变量要被声明为final类型