讀寫鎖適用讀多寫少的場景,讀寫鎖需求必須知足條件:dom
1.一個線程對共享數據read時,同時容許另一個線程能夠並行read操做ide
2.一個線程對共享數據read時,不容許同時另一個線程進行write操做測試
3.一個線程對共享數據write時,不容許同時另一個線程進行write操做this
第一步:線程
建立一個讀寫鎖,優先寫操做進行,爲了在讀多寫少的場景下,能更多執行寫操做。code
public class ReadWriteLock { private int readingReaders = 0; private int waitingReaders = 0; private int writingWriters = 0; private int waitingWriters = 0; private boolean preferWriter = true; public ReadWriteLock() { this(true); } public ReadWriteLock(boolean preferWriter) { this.preferWriter = preferWriter; } public synchronized void readLock() throws InterruptedException { try { this.waitingReaders++; while (writingWriters > 0 || (preferWriter && waitingWriters > 0)) { this.wait(); } this.readingReaders++; }finally { this.waitingReaders--; } } public synchronized void readUnLock() { this.readingReaders--; this.notifyAll(); } public synchronized void writeLock() throws InterruptedException { try { this.waitingWriters++; while(writingWriters > 0 || readingReaders > 0) { this.wait(); } this.writingWriters++; }finally { this.waitingWriters--; } } public synchronized void writeUnLock() { this.writingWriters--; this.notifyAll(); } }
第二步:對象
建立一個共享數據對象,用於讀寫操做get
public class ShareData { private final char[] buffer; private final ReadWriteLock lock = new ReadWriteLock(); public ShareData(int size) { this.buffer = new char[size]; for (int i = 0; i < buffer.length; i++) { buffer[i] = '*'; } } public char[] read() throws InterruptedException { try{ lock.readLock(); return this.doRead(); }finally { lock.readUnLock(); } } public void write(char c) throws InterruptedException { try{ lock.writeLock(); this.doWrite(c); }finally { lock.writeUnLock(); } } private void doWrite(char c) { for (int i = 0; i < buffer.length; i++) { buffer[i] = c; slowly(10); } } private char[] doRead() { char[] newBuf = new char[buffer.length]; for (int i = 0; i < buffer.length; i++) { newBuf[i] = buffer[i]; } slowly(500); return newBuf; } private void slowly(int ms) { try { Thread.sleep(ms); } catch (InterruptedException e) { e.printStackTrace(); } } }
第三步:it
建立一個寫線程,對共享對象進行寫操做io
public class WriterWorker extends Thread{ private static final Random random = new Random(System.currentTimeMillis()); private final ShareData data; private final String filler; private int index; public WriterWorker(ShareData data, String filler) { this.data = data; this.filler = filler; } @Override public void run() { try { while(true) { char c = nextChar(); data.write(c); Thread.sleep(random.nextInt(1000)); } } catch (InterruptedException e) { e.printStackTrace(); } } public char nextChar() { char c = filler.charAt(index); index++; if(index >= filler.length()) { index = 0; } return c; } }
第四步:
建立一個讀線程,對共享對象進行讀操做,並輸出讀數據內容
ublic class ReaderWorker extends Thread{ private final ShareData data; public ReaderWorker(ShareData data) { this.data = data; } @Override public void run() { try { while (true) { char[] readBuffer = data.read(); System.out.println(Thread.currentThread().getName() + " reads " + String.valueOf(readBuffer)); } } catch (InterruptedException e) { e.printStackTrace(); } } }
第五步:
建立一個讀多寫少的測試類
public class ReadWriteLockClient { public static void main(String[] args) { final ShareData shareData = new ShareData(10); new ReaderWorker(shareData).start(); new ReaderWorker(shareData).start(); new ReaderWorker(shareData).start(); new ReaderWorker(shareData).start(); new ReaderWorker(shareData).start(); new WriterWorker(shareData, "ddjifjsidjfisd").start(); new WriterWorker(shareData, "DDJIFJSIDJFISD").start(); } }
第六步:
查看打印結果
Thread-0 reads ********** Thread-1 reads ********** Thread-2 reads ********** Thread-4 reads ********** Thread-3 reads ********** Thread-0 reads DDDDDDDDDD Thread-1 reads DDDDDDDDDD Thread-2 reads DDDDDDDDDD Thread-4 reads DDDDDDDDDD Thread-3 reads DDDDDDDDDD Thread-3 reads dddddddddd Thread-1 reads dddddddddd Thread-0 reads dddddddddd Thread-2 reads dddddddddd Thread-4 reads dddddddddd Thread-4 reads JJJJJJJJJJ Thread-3 reads JJJJJJJJJJ Thread-0 reads JJJJJJJJJJ Thread-1 reads JJJJJJJJJJ Thread-2 reads JJJJJJJJJJ Thread-2 reads IIIIIIIIII Thread-3 reads IIIIIIIIII Thread-1 reads IIIIIIIIII Thread-0 reads IIIIIIIIII Thread-4 reads IIIIIIIIII