JAva同時プログラミング(六)の読み書きロック

2645 ワード

一、読み書きロック
複数のスレッドが同じデータにアクセスする際にスレッドセキュリティの問題があることを知っていますが、データを読み取るだけではセキュリティの問題はありません.複数のスレッドが同時にデータを読み取ると、反発しないようにすることができます.複数のスレッドがデータを修正(書き込み)したり、書き込み中に反発させたりすることで、スレッドの安全性を確保し、パフォーマンスを向上させることができます.
ReadWriteLockは、読み取り専用操作と書き込み操作のペアに関連するロックを維持します.writerがない限り、読み出しロックは複数のreaderスレッドで同時に保持できます.書き込みロックは排他的です.
リード・ライト・ロックにより、リード・ライト・ロック(リード・バウンド、リード・ライト・バウンド)よりも共有データへの同時アクセスが向上します.共有データを変更できるのは一度に1つのスレッド(writerスレッド)のみですが、多くの場合、任意の数のスレッドが共有データ(readerスレッド)を同時に読み出すことができ、読み取り-書き込みロックが利用されます.理論的には、リードライトロックを使用することによって許容される同時性の増強は、反発ロックと比較して、より大きな性能向上をもたらす.
二、読み書きロック特性1.再入
このロックを使用すると、readerとwriterはReentrantLockのスタイルに従って読み取りロックまたは書き込みロックを再取得できます.書き込みスレッドが保持するすべての書き込みロックが解放された後、readerの再読み込みが許可されます.
またwriterはリードロックを取得できるが,逆に成立しない.他のアプリケーションでは、読み込みロック状態で読み取り操作を実行するメソッドを呼び出したりコールバックしたりする間に書き込みロックを保持する場合に便利です.readerが書き込みロックを取得しようとすると、決して成功しません.
2.ロックダウングレード
リエントラントはまた、書き込みロックから読み出しロックに降格することを可能にし、その実現形態は、書き込みロックを取得してから読み出しロックを取得し、最後に書き込みロックを解放することである.ただし、読み込みロックから書き込みロックにアップグレードすることは不可能です.
3.ロック取得の割り込み
読み込みロックと書き込みロックは、ロック取得中の割り込みをサポートします.
4.Conditionは書き込みロックをサポートし、書き込みロックに対してReentrantLock.newCondition()が提供するCondition実装がReentrantLockに対して行った動作と同じ動作を実現するCondition実装を提供する.もちろん、このConditionは書き込みロックにのみ使用できます.
読み込みロックはConditionをサポートしていません.readLock().newCondition()はUnsupportedOperationExceptionを放出します.
package com.dason.second;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 *              ,      ,      
 * @author Dason
 *
 */
public class CacheDemo {

	private Map cache = new HashMap();
	private ReadWriteLock rwl = new ReentrantReadWriteLock();
	
	public static void main(String[] args) {
		new Thread() {
			public void run() {
				Object obj = new CacheDemo().getData("a");
				System.out.println(obj);
			};
		}.start();
	}
	
	public  Object getData(String key){
		//1.    
		rwl.readLock().lock();
		Object value = null;
		try{
			value = cache.get(key);
			if(value == null){
				//2.        ,    ,
				rwl.readLock().unlock();
				//3.    .             ,      ,      
				//                     
				rwl.writeLock().lock();//①
				try{
					//3.              ①         
					if(value==null){
						// value   ,    .
						value = "aaaa";//    queryDB();
					}
					//4.   ,      .
					rwl.readLock().lock();
				}finally{
					rwl.writeLock().unlock();
				}
			}
			//  value,         ,       
			//use(value);
		}finally{
			rwl.readLock().unlock();
		}
		return value;
	}
}