Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android多線程研究(9)——線程鎖Lock

Android多線程研究(9)——線程鎖Lock

編輯:關於Android編程

在前面我們在解決線程同步問題的時候使用了synchronized關鍵字,今天我們來看看Java 5.0以後提供的線程鎖Lock.

\

Lock接口的實現類提供了比使用synchronized關鍵字更加靈活和廣泛的鎖定對象操作,而且是以面向對象的方式進行對象加鎖。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD48cD48cHJlIGNsYXNzPQ=="brush:java;"> @Override public void run() { while(true){ Lock lock = new ReentrantLock(); try { lock.lock(); Thread.sleep(new Random().nextInt(3000)); String data = readData(); System.out.print("讀取數據: " + data); } catch (InterruptedException e) { e.printStackTrace(); }finally{ lock.unlock(); } } }

讀寫鎖:分為讀鎖和寫鎖,多個讀鎖不互斥,讀鎖與寫鎖互斥,寫鎖與寫鎖互斥,這是由JVM控制的。

import java.util.Random;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;


public class ReadWriteLockTest {
	static ReadWriteLock rwl = new ReentrantReadWriteLock();
	
	private static String data = null;
	public static void main(String[] args) {
		Runnable runnable1 = new MyRunnable1();
		Runnable runnable2 = new MyRunnable2();
		for(int i=0; i<3; i++){
			new Thread(runnable1).start();
			new Thread(runnable2).start();
		}
	}
	
	static class MyRunnable1 implements Runnable{
		
		@Override
		public void run() {
			writeData("" + new Random().nextInt(100));	
		}
	}
	
	static class MyRunnable2 implements Runnable{

		@Override
		public void run() {
			readData();		
		}
	}
	
	private static void writeData(String var){
		rwl.writeLock().lock();
		try {
			System.out.println(Thread.currentThread().getName() + " 准備寫");
			Thread.sleep(new Random().nextInt(3000));
			data = var;
			System.out.println(Thread.currentThread().getName() + " 寫完畢");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			rwl.writeLock().unlock();
		}
		
	}
	
	private static void readData(){
		rwl.readLock().lock();  //用讀鎖鎖住
		try {
			System.out.println(Thread.currentThread().getName() + " 准備讀");
			Thread.sleep(new Random().nextInt(3000));
			System.out.println(Thread.currentThread().getName() + " 讀完畢");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			rwl.readLock().unlock();
		}
	}
}
\

用過Hibernate框架的朋友可能知道,Hibernate查詢數據庫有緩存機制,如果某個數據在內存中存在則可以並發的去讀取,如果緩存中沒有數據則需要互斥的去從數據庫取數據。

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


public class CacheDemo {
	private Map cache = new HashMap();
	public static void main(String[] args) {
		
	}
	
	private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
	/**
	 * 實現多個並發讀,互斥的寫 	
	 * @param key
	 * @return
	 */
	public Object getData(String key){
		rwl.readLock().lock();
		Object value = null;
		try{
			value = cache.get(key);
			if(value == null){
				rwl.readLock().unlock();  //釋放讀鎖
				rwl.writeLock().lock();   //添加寫鎖
				try{
					if(value == null){  //放置其他線程加載數據
						value = "去數據庫查詢"; //這裡模擬從數據庫查詢
						if(value == null){
							//TODO 拋出異常
						}
					}
				}finally{
					rwl.writeLock().unlock();
				}
				rwl.readLock().lock();  //鎖還給讀線程
			}
		}finally{
			rwl.readLock().unlock();
		}
		return value;
	}
}
上面獲取數據的大概過程如下:

1、獲取讀鎖,讀取數據

2、如果有數據則直接返回,並釋放讀鎖讓其他線程讀。

3、如果內存中沒有數據則從數據庫寫入內存,釋放讀鎖並添加寫鎖(這樣寫入數據就可以達到可以互斥)

4、讀入內存後釋放寫鎖並還回讀鎖(和後面的unlock()對應)

5、如果在添加寫鎖的時候同時有多個線程,則只能有其中一個線程搶到鎖,等擁有鎖的線程釋放寫鎖後,其他線程就會搶到寫鎖,但是此時數據已經寫入內存,則需要判斷內存數據是否為null如果不為null則直接釋放寫鎖。


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved