サンプル
* java.util.concurrent でもっと簡単に書けるらしいが、勉強なので真面目に書くhttp://blogs.yahoo.co.jp/dk521123/32538961.html
Main.java
public class Main { public static void main(String[] args) { DataStocker stocker = new DataStocker(10); new ReaderThread(stocker).start(); new ReaderThread(stocker).start(); new ReaderThread(stocker).start(); new ReaderThread(stocker).start(); new ReaderThread(stocker).start(); new WriterThread(stocker, "ABCDEFGHIJ").start; new WriterThread(stocker, "0123456789").start; } }
DataStocker.java
SharedResourcepublic class DataStocker { private final char[] targetData; // ここが、読み書き対象のデータ本体 private final ReadWriteLock lock = new ReadWriteLock(); public DataStocker(int size) { this.targetData = new char[size]; for (int i = 0; i < this.targetData.length; i++) { this.targetData[i] = '*'; } } public List<Person> readData() throws InterruptedException { this.lock.readLock(); try { return read(); } finally { this.lock.readUnlock(); } } public void writeData(char value) throws InterruptedException { this.lock.writeLock(); try { return write(value); } finally { this.lock.writeUnlock(); } } private List<Person> read() throws InterruptedException { char[] newData = new char[this.targetData.lenght]; for (int i = 0; i < this.targetData.length; i++) { newData[i] = this.targetData[i]; } this.slow(); return newData; } private void write(char value) throws InterruptedException { for (int i = 0; i < this.targetData.length; i++) { targetData[i] = value; this.slow(); } } // For Test private void slow() { try { Thread.sleep(100); } catch (Exception ex) { } } }
ReaderThread.java
Readerpublic class ReaderThread extends Thread { private final DataStocker stocker; public WriterThread(DataStocker stocker) { this.stocker = stocker; } public void run() { try { while(true) { char[] readValues = this.stocker.readData(); System.out.println("Result : " + Thread.currentThread().getName() + " Read Values : " + String.valueOf(readValues)); } } catch (Exception ex) { } } }
WriterThread.java
Writerpublic class WriterThread extends Thread { private static final Random random = new Random(); private final DataStocker stocker; private final String stockData; private int index = 0; public WriterThread(DataStocker stocker, String stockData) { this.stocker = stocker; this.stockData = stockData; } public void run() { try { char value = this.nextValue(); this.writeData(value); Thread.sleep(random.nextInt(3000)); } catch (Exception ex) { } } private char nextValue() { char value = this.filler.charAt(this.index); this.index++; if (this.index >= this.stockData.length()) { this.index = 0; } return value; } }
ReadWriteLock.java
ReadWriteLockReentrantLock(再入可能ロック)と同じ?
public final class ReadWriteLock { private int readingThreadNumber = 0; private int waitingWriterThreadNumber = 0; private int writingThreadNumber = 0; private boolean isReadyForWriter = true; public synchronized void readLock() throws InterruptedException { while (this.writingThreadNumber > 0 || (this.isReadyForWriter && this.waitingWriterThreadNumber > 0)) { wait(); } this.readingThreadNumber++; } public synchronized void readUnlock() { this.readingThreadNumber--; this.isReadyForWriter = true; notifyAll(); } public synchronized void writeLock() throws InterruptedException { this.waitingWriterThreadNumber++; try { while (this.readingThreadNumber > 0 || writingThreadNumber > 0) { wait(); } } fianlly { this.waitingWriterThreadNumber--; } this.writingThreadNumber++; } public synchronized void writeUnlock() { this.writingThreadNumber--; this.isReadyForWriter = false; notifyAll(); } }
関連するデザインパターン
Immutable パターン
* 登場人物「Reader」で排他制御をなくするために使用
Single Threaded Execution パターン
* 登場人物「Writer」のスレッドを1個に限定するために使用
Guarded Suspension パターン
* 登場人物「ReadWriteLock」を作る時に使用http://blogs.yahoo.co.jp/dk521123/32928012.html
Before/After パターン
* ロックの解放忘れを防ぐために使用
Strategized Locking パターン
* 排他制御のパフォーマンスにおいて、更に柔軟な排他制御を実現しているらしい。
参考文献
http://pgcafe.moo.jp/JAVA/thread/main_5.htmConcurrentとの性能比較
http://gurimmer.lolipop.jp/daihakken/2012/03/21/javareadwritelock%E3%81%A8concurrent%E3%81%AE%E6%80%A7%E8%83%BD%E6%AF%94%E8%BC%83/ロックについて
http://www.horobi.com/tips/SmartLock/ReentrantLock(再入可能ロック)
http://d.hatena.ne.jp/yone098/20070109/1168321219https://www.ibm.com/developerworks/jp/java/library/j-jtp10264/
http://d.hatena.ne.jp/unageanu/20070419/1176959204