package com.zhengweihao.test.concurrent.readwritelock; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; import org.junit.Test; public class ReadWriteLockTest { private int runOver = 0; private static final ExecutorService pool = Executors .newFixedThreadPool(Runtime.getRuntime().availableProcessors()); private static final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); private static final ReadLock readLock = rwl.readLock(); private static final WriteLock writeLock = rwl.writeLock(); /** * 测试读锁不互斥 */ @Test public void testReadReadLock() { runOver = 2; final int sleepTime = 1000; pool.execute(new Runnable() { public void run() { readLock.lock(); System.out.println("read1 locked " + nowString() + ".."); sleep(sleepTime); System.out.println("read1 unlocked " + nowString() + ".."); runOver--; readLock.unlock(); } }); pool.execute(new Runnable() { public void run() { readLock.lock(); System.out.println("read2 locked " + nowString() + ".."); sleep(sleepTime); System.out.println("read2 unlocked " + nowString() + ".."); runOver--; readLock.unlock(); } }); while (runOver > 0) { sleep(sleepTime); } } /** * 测试读锁阻塞写锁 */ @Test public void testReadWriteLock() { runOver = 2; final int sleepTime = 1000; pool.execute(new Runnable() { public void run() { readLock.lock(); System.out.println("read locked " + nowString() + ".."); sleep(sleepTime); System.out.println("read unlocked " + nowString() + ".."); runOver--; readLock.unlock(); } }); pool.execute(new Runnable() { public void run() { writeLock.lock(); System.out.println("write locked " + nowString() + ".."); sleep(sleepTime); System.out.println("write unlocked " + nowString() + ".."); runOver--; writeLock.unlock(); } }); while (runOver > 0) { sleep(sleepTime); } } /** * 测试写锁阻塞读锁 */ @Test public void testWriteReadLock() { runOver = 2; final int sleepTime = 1000; pool.execute(new Runnable() { public void run() { writeLock.lock(); System.out.println("write locked " + nowString() + ".."); sleep(sleepTime); System.out.println("write unlocked " + nowString() + ".."); runOver--; writeLock.unlock(); } }); pool.execute(new Runnable() { public void run() { readLock.lock(); System.out.println("read locked " + nowString() + ".."); sleep(sleepTime); System.out.println("read unlocked " + nowString() + ".."); runOver--; readLock.unlock(); } }); while (runOver > 0) { sleep(sleepTime); } } /** * 测试写锁互斥 */ @Test public void testWriteWriteLock() { runOver = 2; final int sleepTime = 1000; pool.execute(new Runnable() { public void run() { writeLock.lock(); System.out.println("write1 locked " + nowString() + ".."); sleep(sleepTime); System.out.println("write1 unlocked " + nowString() + ".."); runOver--; writeLock.unlock(); } }); pool.execute(new Runnable() { public void run() { writeLock.lock(); System.out.println("write2 locked " + nowString() + ".."); sleep(sleepTime); System.out.println("write2 unlocked " + nowString() + ".."); runOver--; writeLock.unlock(); } }); while (runOver > 0) { sleep(sleepTime); } } private void sleep(int millis) { try { Thread.sleep(millis); } catch (InterruptedException e) { e.printStackTrace(); } } private String nowString() { Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); return sdf.format(date); } }
运行结果:java
当同时运行两个加读锁的线程时,两个线程不互斥。运行结果为:架构
read2 locked 2016-01-03 12:09:13.. read1 locked 2016-01-03 12:09:13.. read2 unlocked 2016-01-03 12:09:14.. read1 unlocked 2016-01-03 12:09:14..
当先运行加读锁线程,再运行加写锁线程时,读锁将阻塞写锁。运行结果为:性能
read locked 2016-01-03 12:12:43.. read unlocked 2016-01-03 12:12:44.. write locked 2016-01-03 12:12:44.. write unlocked 2016-01-03 12:12:45..
当先运行加写锁线程,再运行加读锁的线程时,读锁等待写锁解锁。运行结果为:测试
write locked 2016-01-03 12:14:27.. write unlocked 2016-01-03 12:14:29.. read locked 2016-01-03 12:14:29.. read unlocked 2016-01-03 12:14:30..
当两个加写锁的线程前后运行,后者将等待前者解锁。运行结果为:线程
write1 locked 2016-01-03 12:16:05.. write1 unlocked 2016-01-03 12:16:06.. write2 locked 2016-01-03 12:16:06.. write2 unlocked 2016-01-03 12:16:07..
测试结果:code
可见读写锁容许多个线程同时进行读操做;而当有读操做时进行写操做,写操做将等待读操做完成后再进行;当有写操做时,不论读或是写,都将被阻塞。这种程序就保证了有写操做时,不出现脏数据,同时也保证了较好的读性能,很是适合读多写少的架构。
orm