synchronized、Lock、ReadWriteLock(讀寫鎖例子 CacheDemo)

一、synchronized:它是java中的一個關鍵字,它能夠把任意一個非NULL的對象看成鎖。java

1)做用於方法時,鎖住的是對象的實例(this);緩存

2)看成用於靜態方法時,鎖住的是Class實例,又由於Class的相關數據存儲在永久帶PermGen(jdk1.8則是metaspace),永久帶是全局共享的,所以靜態方法鎖至關於類的一個全局鎖,會鎖全部調用該方法的線程;併發

3)synchronized做用於一個對象實例時,鎖住的是全部以該對象爲鎖的代碼塊。性能

 

二、Lock:Lock有一個實現類:ReentrantLock,它實現了Lock裏面的方法,可是使用Lock的時候必須注意它不會像synchronized執行完成以後或者拋出異常以後自動釋放鎖,而是須要你主動釋放鎖,因此咱們必須在使用Lock的時候加上try{}catch{}finally{}塊,而且在finally中釋放佔用的鎖資源。this

Lock和synchronized最大的區別就是當使用synchronized,一個線程搶佔到鎖資源,其餘線程必須等待;而使用Lock,一個線程搶佔到鎖資源,其餘的線程能夠不等待或者設置等待時間,實在搶不到能夠去作其餘的業務邏輯。spa

三、ReadWriteLock(讀讀共享,其餘全互斥):它能夠實現讀寫鎖,當讀取的時候線程會得到read鎖,其餘線程也能夠得到read鎖同時併發的去讀取,可是寫程序運行獲取到write鎖的時候,其餘線程是不能進行操做的,由於write是排它鎖,而上面介紹的兩種無論你是read仍是write沒有搶到鎖的線程都會被阻塞或者中斷,它也是個接口,裏面定義了兩種方法readLock()和readLock(),他的一個實現類是ReentrantReadWriteLock。線程

關於讀寫鎖的一個緩存例子CacheDemo:code

package resource.java.ordinary.mul.thread;

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

/**
 * 一個緩存demo,讀寫鎖例子,實現讀和寫互斥、寫和寫互斥,但有能夠多個併發的讀,可提升系統性能
 * 
 * @author xiao
 */
public class CacheDemo {
	// 數據
	private Map<String, Object> cache = new HashMap<>();
	// 讀寫鎖
	private ReadWriteLock rwl = new ReentrantReadWriteLock();

	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) {
						// 若是沒有數據,則去查DB獲取數據
						value = "XXX";
					}
				} finally {
					// 讀取數據後釋放寫鎖
					rwl.writeLock().unlock();
				}
				// 獲取完數據後,恢復讀鎖,從新讀取數據
				rwl.readLock().lock();
			}
		} finally {
			// 從新讀取數據釋放讀鎖
			value = cache.get(key);
			rwl.readLock().unlock();
		}
		return value;
	}
}
相關文章
相關標籤/搜索