多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國(guó)內(nèi)最全I(xiàn)T社區(qū)平臺(tái) 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁(yè) > php框架 > 框架設(shè)計(jì) > ReentrantReadWriteLock讀寫鎖的使用2

ReentrantReadWriteLock讀寫鎖的使用2

來(lái)源:程序員人生   發(fā)布時(shí)間:2015-02-03 08:40:39 閱讀次數(shù):3284次

本文可作為傳智播客《張孝祥-Java多線程與并發(fā)庫(kù)高級(jí)利用》的學(xué)習(xí)筆記。

這1節(jié)我們做1個(gè)緩存系統(tǒng)。


在讀本節(jié)前
請(qǐng)先瀏覽
ReentrantReadWriteLock讀寫鎖的使用1

初版

public class CacheDemo { private Map<String, Object> cache = new HashMap<String, Object>(); public static void main(String[] args) { CacheDemo cd = new CacheDemo(); System.out.println("ss "+cd.getData2("ss")); System.out.println("ss "+cd.getData2("ss")); System.out.println("mm "+cd.getData2("mm")); System.out.println("mm "+cd.getData2("mm")); } public Object getData2(String key){ Object o=cache.get(key); if (o==null) { //標(biāo)識(shí)1 System.out.println("第1次查 沒(méi)有"+key); o=Math.random(); //實(shí)際上從數(shù)據(jù)庫(kù)中取得 cache.put(key, o); } return o; } }
運(yùn)行結(jié)果:
第1次查  沒(méi)有ss
ss   0.4045014284225158
ss   0.4045014284225158
第1次查  沒(méi)有mm
mm   0.9994663041529088
mm   0.9994663041529088

似乎沒(méi)有問(wèn)題。
你覺(jué)得呢?
如果有3個(gè)線程同時(shí)第1次到了getData2()的標(biāo)識(shí)1處(所查找的key也都1樣),1檢查o為null,然后就去查數(shù)據(jù)庫(kù)。在這類情況下,就等于3個(gè)線程查同1個(gè)key,然后都去了數(shù)據(jù)庫(kù)
這明顯是不公道的。

第2版 synchronized

最簡(jiǎn)單的辦法
    public synchronized Object getData2(String key){
        //.....

    }


第3版 鎖

上1節(jié)我們提到了ReentrantLock可以替換synchronized,前者是1種更加面向?qū)ο蟮脑O(shè)計(jì)。那我們?cè)囋嚒?br>
private Lock l=new ReentrantLock(); //l作為CacheDemo的成員變量 public Object getData3(String key) { l.lock(); Object o=null; try { o = cache.get(key); if (o == null) { // 標(biāo)識(shí)1 System.out.println("第1次查 沒(méi)有" + key); o = Math.random(); // 實(shí)際上從數(shù)據(jù)庫(kù)中取得 cache.put(key, o); } } finally { l.unlock(); } return o; }
第3版可以嗎?
可以個(gè)p。

為何,自己想。


我們得使用ReentrantReadWriteLock,在同1個(gè)方法中既有讀鎖也有寫鎖。

首先我又1個(gè)問(wèn)題:

對(duì)同1個(gè)線程,可以在加了讀鎖后,沒(méi)有解開(kāi)讀鎖前,再加寫鎖嗎?

換句話說(shuō),下面的代碼會(huì)停嗎?

public class CacheDemo { private Map<String, Object> cache = new HashMap<String, Object>(); private ReadWriteLock rwl = new ReentrantReadWriteLock(); public static void main(String[] args) { CacheDemo cd = new CacheDemo(); cd.getData2(); } public void getData2(){ rwl.readLock().lock(); System.out.println(1); rwl.writeLock().lock(); System.out.println(2); rwl.readLock().unlock(); System.out.println(3); rwl.writeLock().unlock(); System.out.println(4); } }
親身試1下,控制臺(tái)輸出1后,程序就不動(dòng)了。

說(shuō)明加寫鎖前,讀鎖得先解開(kāi)。

第4版

即有讀鎖,又有寫鎖
   
public static void main(String[] args) { CacheDemo cd = new CacheDemo(); System.out.println("ss "+cd.getData4("ss")); System.out.println("ss "+cd.getData4("ss")); System.out.println("mm "+cd.getData4("mm")); System.out.println("mm "+cd.getData4("mm")); } public Object getData4(String key){ rwl.readLock().lock(); Object o=null; try { o=cache.get(key); if (o==null) { System.out.println("第1次查 沒(méi)有"+key); rwl.readLock().unlock(); //標(biāo)識(shí)4 rwl.writeLock().lock(); try { if(value==null){ //標(biāo)識(shí)0 value = "aaaa";//實(shí)際調(diào)用 queryDB(); cache.put(key,value); } } finally { rwl.writeLock().unlock(); } rwl.readLock().lock(); //標(biāo)識(shí)1 } }finally { rwl.readLock().unlock(); //標(biāo)注2 } return o; }
結(jié)果
第1次查  沒(méi)有ss
ss   0.5989899889645358
ss   0.5989899889645358
第1次查  沒(méi)有mm
mm   0.8534424949014686

mm   0.8534424949014686

這個(gè)還有3個(gè)問(wèn)題

1為何在標(biāo)識(shí)2處還得解鎖。
這個(gè)答案在上1節(jié)已提過(guò)。

2為何在標(biāo)識(shí)1出還得加鎖?
如果標(biāo)識(shí)1處不加鎖,且程序1直正常履行,那末到標(biāo)識(shí)2處,它解誰(shuí)的鎖?


3為何標(biāo)識(shí)0出還要檢查1次?
如果同時(shí)又3個(gè)線程運(yùn)行到標(biāo)識(shí)4(查找相同的key),其中1個(gè)取得寫鎖,寫入數(shù)據(jù)后,釋放了寫鎖。此時(shí)另外兩個(gè)線程還需要去數(shù)據(jù)庫(kù)跑1趟么?

另外把標(biāo)識(shí)1處的加讀鎖,放到finally的前面稱之為降級(jí)鎖。對(duì)降級(jí)鎖,我目前也不太清楚。
官方文檔中給了1個(gè)例子就是關(guān)于降級(jí)鎖,以下
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(); } } }

感謝glt




生活不易,碼農(nóng)辛苦
如果您覺(jué)得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 91精品一区二区综合在线 | 国产在线原创剧情麻豆 | 欧美日韩中文 | 日韩 欧美 亚洲国产 | 日本欧美一区二区免费视 | 久草在线观看福利视频 | 中国国产一国产一级毛片视频 | 欧美a在线 | 另类激情亚洲 | 国产亚洲欧美日韩国产片 | 秋霞一级特黄真人毛片 | 福利在线国产 | 成人亚欧网站在线观看 | 欧美综合伊人久久 | 亚洲黄色在线观看 | 特黄的欧美毛片 | 国产jlzzjlzz视频免费 | 国产午夜视频在线观看第四页 | 久久久久久久尹人综合网亚洲 | 国产一区二区免费不卡在线播放 | 日韩免费一区二区三区 | 国产日韩不卡免费精品视频 | 国产精品一区三区 | 久久婷婷人人澡人人爱91 | 亚洲另类图片专区 | 中文字幕精品一区二区2021年 | 亚洲成年网站 | 最近中文字幕大全高清视频 | 亚洲码欧美码一区二区三区 | 亚洲人成图片欧美人成图片 | 亚洲免费精品视频 | 波多野结衣视频免费 | 国产精品成人一区二区三区 | 性生生活三级视频观看 | 最近最新免费中文字幕高清 | 国产性色视频 | 国产中文字幕视频在线观看 | 日本中文字幕免费 | 岛国午夜精品视频在线观看 | 中文字幕亚洲欧美日韩不卡 | 特级做a爰片毛片免费看一区 |