Android多線程研究(9)——讀寫鎖
一、什麼是鎖
在Java的util.concurrent.locks包下有關於鎖的介面和類如下:
先看一段代碼:
package com.codeing.snail.test;public class ReadWriteLockTest {public static void main(String[] args) {final Output output = new Output();new Thread(){public void run() {while(true){output.output("CodeingSnail");}};}.start();new Thread(){public void run() {while(true){output.output("陽光小強");}};}.start();}static class Output{public void output(String name){char[] arry = name.toCharArray();for(int i = 0; i < arry.length; i++){System.out.print(arry[i]);}System.out.println();}}}
輸出的結果如下:
如果我們想讓“CodeingSnail"和“陽光小強"兩個字串都能完整輸出,就需要使用synchronized關鍵字將輸出部分聲明,如下:
public synchronized void output(String name){char[] arry = name.toCharArray();for(int i = 0; i < arry.length; i++){System.out.print(arry[i]);}System.out.println();}
其實,除了synchronized關鍵字之外,還可以使用鎖(Lock)來實現同步。
ReentrantLock lock = new ReentrantLock();public void output(String name){lock.lock();try{char[] arry = name.toCharArray();for(int i = 0; i < arry.length; i++){System.out.print(arry[i]);}System.out.println();}finally{lock.unlock();}}上面代碼使用try...finally語句塊是為了防止出現異常執行不到unlock方法,ReentrantLock是Lock的實作類別,Lock的作用和synchronized類似,但更加物件導向,要實現同步就必須使用同一個lock對象。
二、什麼是讀寫鎖讀寫鎖、分為讀鎖和寫鎖,多個讀鎖不互斥,讀鎖與寫鎖互斥,寫鎖與寫鎖互斥。下面我們來看一下API文檔中的一個緩衝器的例子:
class CachedData {Object data;volatile boolean cacheValid;final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();void processCachedData() { rwl.readLock().lock(); if (!cacheValid) { // Must release read lock before acquiring write lock rwl.readLock().unlock(); rwl.writeLock().lock(); try { // Recheck state because another thread might have // acquired write lock and changed state before we did. if (!cacheValid) { data = ... cacheValid = true; } // Downgrade by acquiring read lock before releasing write lock rwl.readLock().lock(); } finally { rwl.writeLock().unlock(); // Unlock write, still hold read } } try { use(data); } finally { rwl.readLock().unlock(); } }}假如有多個線程來讀取資料,第一個線程進來先上一把寫鎖進行資料寫入(先釋放讀鎖),寫入完成後將寫鎖降級為讀鎖(第15行),其他線程在讀取資料的時候上讀鎖後互不影響。這樣可以提高讀取效率。