读写锁相对于线程互斥的优势在于高效,它不会对两个读线程进行盲目的互斥处理,当读线程数量多于写线程尤其如此,当全是写线程时两者等效。(多用于读多写少时使用)
1.读锁可以允许多个进行读操作的线程同时进入,但不允许写进程进入。
2.写锁只允许一个写进程进入,在这期间任何进程都不能再进入。
注意:每个读写锁都有挂锁和解锁,最好将每一对挂锁和解锁操作都用try、finally来套入中间的代码,这样就会防止因异常的发生而造成死锁得情况。
例子:
import java.util.Random; import java.util.concurrent.locks.*; public class ReadWriteLockTest { public static void main(String[] args) { final TheData myData = new TheData(); // 这是各线程的共享数据 for (int i = 0; i < 3; i++) { // 开启3个读线程 new Thread(new Runnable() { @Override public void run() { while (true) { myData.get(); } } }).start(); } for (int i = 0; i < 3; i++) { // 开启3个写线程 new Thread(new Runnable() { @Override public void run() { while (true) { myData.put(new Random().nextInt(10000)); } } }).start(); } } } class TheData { private Object data = null; private ReadWriteLock rwl = new ReentrantReadWriteLock(); public void get() { rwl.readLock().lock(); // 读锁开启,读线程均可进入 try { // 用try finally来防止因异常而造成的死锁 System.out.println(Thread.currentThread().getName() + "is ready to read"); Thread.sleep(new Random().nextInt(100)); System.out.println(Thread.currentThread().getName() + "have read date" + data); } catch (InterruptedException e) { e.printStackTrace(); } finally { rwl.readLock().unlock(); // 读锁解锁 } } public void put(Object data) { rwl.writeLock().lock(); // 写锁开启,这时只有一个写线程进入 try { System.out.println(Thread.currentThread().getName() + "is ready to write"); Thread.sleep(new Random().nextInt(100)); this.data = data; System.out.println(Thread.currentThread().getName() + "have write date" + data); } catch (InterruptedException e) { e.printStackTrace(); } finally { rwl.writeLock().unlock(); // 写锁解锁 } } }
参考(ReentrantReadWriteLock类和ReentrantLock类的区别): http://blog.csdn.net/kai_wei_zhang/article/details/8197061