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