Posted on 2011-10-17 16:59
瘋狂 閱讀(1121)
評論(0) 編輯 收藏 所屬分類:
concurrent
線程讀寫同一個對象的數據是很普遍的,通常,要避免讀寫沖突,必須保證任何時候僅有一個線程在寫入,有線程正在讀取的時候,寫入操作就必須等待。簡單說,就是要避免“寫-寫”沖突和“讀-寫”沖突。但是同時讀是允許的,因為“讀-讀”不沖突,而且很安全。
沖jdk1.5開始可以使用ReadWriteLock類來防止讀寫沖突.它有一個已有的實現ReentrantReadWriteLock。
ReentrantReadWriteLock使用內部維護的讀寫鎖來防止讀寫沖突;

public ReentrantReadWriteLock.WriteLock writeLock()
{ return writerLock; }

public ReentrantReadWriteLock.ReadLock readLock()
{ return readerLock; }示例代碼如下:
public class RreadWriteLockTest {
ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
public int i = 0;
//讀取
public void read() throws InterruptedException{
readWriteLock.readLock().lock();//獲取讀鎖
System.out.println("read thread:"+Thread.currentThread().getName());
Thread.sleep(10000);
System.out.println("read:"+i);
readWriteLock.readLock().unlock();
}
//寫入
public void write() throws InterruptedException{
readWriteLock.writeLock().lock();//獲取寫鎖
System.out.println("write thread:"+Thread.currentThread().getName());
Thread.sleep(10000);
i = 2;
System.out.println("write:"+i);
readWriteLock.writeLock().unlock();
}
}
測試代碼:
1 測試兩個同時讀的,結果都能同時讀取。
2 測試一個讀,一個寫的,需要其中一個釋放鎖之后才能進行另外一個操作
public static void main(String[] args) throws InterruptedException {
final RreadWriteLockTest lockTest= new RreadWriteLockTest();
new Thread(new Runnable() {
@Override
public void run() {
try {
lockTest.write();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
Thread.sleep(2000);
new Thread(new Runnable() {
@Override
public void run() {
try {
lockTest.read();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}
打印如下:
write thread:Thread-0執(zhí)行完之后(10秒之后)才執(zhí)行read thread:Thread-1
注意:執(zhí)行完以后一定要執(zhí)行unlock,要不lock的計數沒有-1,這樣對應read或者write的操作將無法進行,一直等待。