电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

Java 重入鎖和讀寫鎖的具體使用

瀏覽:2日期:2022-08-15 14:38:04
重入鎖

重入鎖 ReentrantLock,顧名思義,就是支持重進入的鎖,它表示該鎖能夠支持一個線程對資源的重復加鎖。除此之外,該鎖還支持獲取鎖時的公平和非公平性選擇

所謂不支持重進入,可以考慮如下場景:當一個線程調用 lock() 方法獲取鎖之后,如果再次調用 lock() 方法,則該線程將會被自己阻塞,原因是在調用 tryAcquire(int acquires) 方法時會返回 false,從而導致線程阻塞

synchronize 關鍵字隱式的支持重進入,比如一個 synchronize 修飾的遞歸方法,在方法執行時,執行線程在獲取鎖之后仍能連續多次地獲得該鎖。ReentrantLock 雖然不能像 synchronize 關鍵字一樣支持隱式的重進入,但在調用 lock() 方法時,已經獲得鎖的線程,能夠再次調用 lock() 方法獲取鎖而不被阻塞

1. 實現重進入

重進入特性的實現需要解決以下兩個問題:

線程再次獲取鎖鎖需要去識別獲取鎖的線程是否為當前占據鎖的線程,如果是,則再次成功獲取

鎖的最終釋放線程重復 n 次獲取鎖,隨后在第 n 次釋放該鎖后,其他線程能獲取到鎖。實現此功能,理應考慮使用計數

ReentrantLock 通過組合自定義同步器來實現鎖的獲取與釋放,以非公平鎖實現為例,獲取同步狀態的代碼如下所示,主要是增加了再次獲取同步狀態的處理邏輯

final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } // 判斷當前線程是否為獲取鎖的線程 else if (current == getExclusiveOwnerThread()) { // 將同步值進行增加,并返回 true int nextc = c + acquires; if (nextc < 0) throw new Error('Maximum lock count exceeded'); setState(nextc); return true; } return false;}

考慮到成功獲取鎖的線程再次獲取鎖,只是增加同步狀態值,這也就要求 ReentrantLock 在釋放同步狀態時減少同步狀態值,該方法代碼如下:

protected final boolean tryRelease(int releases) { // 減少狀態值 int c = getState() - releases; if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; // 當同步狀態為0,將占有線程設為null,并返回true,表示釋放成功 if (c == 0) { free = true; setExclusiveOwnerThread(null); } setState(c); return free;}2. 公平與非公平獲取鎖的區別

如果一個鎖是公平的,那么鎖的獲取順序就應該符合請求的絕對時間順序,也即 FIFO。回顧上一節,非公平鎖只要 CAS 設置同步狀態成功,即表示當前線程獲取了鎖,而公平鎖則不同,代碼如下:

protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { /* * 唯一不同的就是判斷條件多了 hasQueuedPredecessors() * 該方法用來判斷當前節點是否有前驅節點 * 如果該方法返回 true,表示有線程比當前線程更早請求獲取鎖 * 因此需要等待前驅線程釋放鎖之后才能繼續獲取鎖 */ if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) throw new Error('Maximum lock count exceeded'); setState(nextc); return true; } return false;}讀寫鎖

之前提到的鎖基本都是排它鎖,同一時刻只允許一個線程訪問,而讀寫鎖在同一時刻可以允許多個線程訪問,但在寫線程訪問時,所有的讀線程和其他寫線程均被阻塞。讀寫鎖維護了一對鎖,一個讀鎖和一個寫鎖,通過分離讀鎖和寫鎖,使得并發性相比一般的排它鎖有了很大提升

1. 接口示例

下面通過緩存示例說明讀寫鎖的使用方式

public class Cache { static Map<String, Object> map = new HashMap<>(); static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); static Lock r = rwl.readLock(); static Lock w = rwl.writeLock(); /** * 獲取一個 key 對應的 value */ public static Object get(String key) { r.lock(); try { return map.get(key); } finally { r.unlock(); } } /** * 設置 key 對應的 value,并返回舊的 value */ public static Object put(String key, Object value) { w.lock(); try { return map.put(key, value); } finally { w.unlock(); } } /** * 清空所有的內容 */ public static void clear() { w.lock(); try { map.clear(); } finally { w.unlock(); } }}2. 讀寫狀態的設計

讀寫鎖同樣依賴自定義同步器來實現功能,而讀寫狀態就是其同步器狀態。讀寫鎖的自定義同步器需要在同步狀態(一個整型變量)上維護多個讀線程和一個寫線程的狀態,為此需要讀寫鎖將變量切分成兩部分,高 16 位表示讀,低 16 位表示寫

Java 重入鎖和讀寫鎖的具體使用

上圖表示一個線程已經獲取了寫鎖,且重進入了兩次,同時也連續兩次獲取了讀鎖。通過位運算可以迅速確定讀和寫各自的狀態,假設當前同步狀態值為 S,則:

寫狀態等于 S & 0x0000FFFF(將高 16 位全部抹去) 讀狀態等于 S >>> 16(無符號右移 16 位) 當寫狀態增加 1 時,等于 S + 1 當讀狀態增加 1 時,等于 S + (1<<6),也就是 S + 0x00010000

根據狀態的劃分能得出一個結論:S 不等于 0 時,當寫狀態(S & 0x0000FFFF)等于 0 時,則讀狀態(S >>> 16)大于 0,即讀鎖已被獲取

3. 寫鎖的獲取與釋放

寫鎖是一個支持重進入的排它鎖。如果當前線程已經獲取了寫鎖,則增加寫狀態。如果當前線程在獲取寫鎖時,讀鎖已被獲取,或者該線程不是獲取寫鎖的線程,則當前線程進入等待狀態,獲取寫鎖的代碼如下:

protected final boolean tryAcquire(int acquires) { Thread current = Thread.currentThread(); int c = getState(); // exclusiveCount 方法會用 c & 0x0000FFFF,即得出寫狀態個數 int w = exclusiveCount(c); if (c != 0) { // 根據上面提到的推論,c 不等于 0,而 w 等于 0,證明存在讀鎖 // 當前線程也不是獲取了寫鎖的線程 if (w == 0 || current != getExclusiveOwnerThread()) return false; if (w + exclusiveCount(acquires) > MAX_COUNT) throw new Error('Maximum lock count exceeded'); setState(c + acquires); return true; } if (writerShouldBlock() || !compareAndSetState(c, c + acquires)) return false; setExclusiveOwnerThread(current); return true;}

寫鎖的每次釋放均會減少寫狀態,當寫狀態為 0 時表示寫鎖已被釋放,從而等待的讀寫線程能夠繼續訪問讀寫鎖,同時前次寫線程的修改對后續讀寫線程可見

4. 讀鎖的獲取與釋放

讀鎖是一個支持重進入的共享鎖,它能被多個線程同時獲取,在沒有其他寫線程訪問時,讀鎖總能被成功獲取,這里對獲取讀鎖的代碼做了簡化:

protected final int tryAcquireShared(int unused) { for(;;) { int c = getState(); int nextc = c + (1<<16); if(nextc < c) { throw new Error('Maximum lock count exceeded'); } // 如果其他線程已經獲取寫鎖,則讀取獲取失敗 if(exclusiveCount(c) != 0 && owner != Thread.currentThread()) { return -1; } if(compareAndSetState(c, nextc)) { return 1; } }}

讀鎖的每次釋放均減少讀狀態,減少的值是 1<<16

5. 鎖降級

鎖降級指的是寫鎖降級成為讀鎖。如果當前線程擁有寫鎖,然后將其釋放,最后再獲取讀鎖,這種分段完成的過程不能稱之為鎖降級。鎖降級是指把持住寫鎖,再獲取讀鎖,隨后釋放寫鎖的過程

public void processData() { readLock.lock(); if(!update) { // 必須先釋放讀鎖 readLock.unlock(); // 鎖降級從寫鎖獲取到開始 writeLock.lock(); try { if(!update) { // 準備數據的流程(略) update = true; } readLock.lock(); } finally { writeLock.unlock(); } } try { // 使用數據的流程(略) } finally { readLock.unlock(); }}

上例中,當數據發生變更,則 update(使用 volatile 修飾)被設置為 false,此時所有訪問 processData 方法的線程都能感知到變化,但只有一個線程能獲取到寫鎖,其余線程會被阻塞在寫鎖的 lock 方法上。當前線程獲取寫鎖完成數據準備之后,再次獲取讀鎖,隨后釋放寫鎖,完成鎖降級

到此這篇關于Java 重入鎖和讀寫鎖的具體使用的文章就介紹到這了,更多相關Java 重入鎖和讀寫鎖內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Java
相關文章:
主站蜘蛛池模板: 无尘烘箱_洁净烤箱_真空无氧烤箱_半导体烤箱_电子防潮柜-深圳市怡和兴机电 | 岩棉板|岩棉复合板|聚氨酯夹芯板|岩棉夹芯板|彩钢夹芯板-江苏恒海钢结构 | 破碎机锤头_合金耐磨锤头_郑州宇耐机械工程技术有限公司 | 翅片管散热器价格_钢制暖气片报价_钢制板式散热器厂家「河北冀春暖气片有限公司」 | 手持气象站_便携式气象站_农业气象站_负氧离子监测站-山东万象环境 | 免费个人pos机申请办理-移动pos机刷卡-聚合收款码办理 | 皮带式输送机械|链板式输送机|不锈钢输送机|网带输送机械设备——青岛鸿儒机械有限公司 | 青岛侦探_青岛侦探事务所_青岛劝退小三_青岛婚外情取证-青岛王军侦探事务所 | 2025黄道吉日查询、吉时查询、老黄历查询平台- 黄道吉日查询网 | 智能汉显全自动量热仪_微机全自动胶质层指数测定仪-鹤壁市科达仪器仪表有限公司 | lcd条形屏-液晶长条屏-户外广告屏-条形智能显示屏-深圳市条形智能电子有限公司 | 哈尔滨治「失眠/抑郁/焦虑症/精神心理」专科医院排行榜-京科脑康免费咨询 一对一诊疗 | 槽钢冲孔机,槽钢三面冲,带钢冲孔机-山东兴田阳光智能装备股份有限公司 | 电气控制系统集成商-PLC控制柜变频控制柜-非标自动化定制-电气控制柜成套-NIDEC CT变频器-威肯自动化控制 | 地磅-电子地磅维修-电子吊秤-汽车衡-无人值守系统-公路治超-鹰牌衡器 | 西子馋火锅鸡加盟-太原市龙城酉鼎餐饮管理有限公司 | 圣才学习网-考研考证学习平台,提供万种考研考证电子书、题库、视频课程等考试资料 | 深圳美安可自动化设备有限公司,喷码机,定制喷码机,二维码喷码机,深圳喷码机,纸箱喷码机,东莞喷码机 UV喷码机,日期喷码机,鸡蛋喷码机,管芯喷码机,管内壁喷码机,喷码机厂家 | 高清视频编码器,4K音视频编解码器,直播编码器,流媒体服务器,深圳海威视讯技术有限公司 | 磁力轮,磁力联轴器,磁齿轮,钕铁硼磁铁-北京磁运达厂家 | 等离子表面处理机-等离子表面活化机-真空等离子清洗机-深圳市东信高科自动化设备有限公司 | 游泳池设计|设备|配件|药品|吸污机-东莞市太平洋康体设施有限公司 | 喷砂机厂家_自动除锈抛丸机价格-成都泰盛吉自动化喷砂设备 | 生鲜配送系统-蔬菜食材配送管理系统-连锁餐饮订货配送软件-挪挪生鲜供应链管理软件 | 管理会计网-PCMA初级管理会计,中级管理会计考试网站 | 衢州装饰公司|装潢公司|办公楼装修|排屋装修|别墅装修-衢州佳盛装饰 | 浙江上沪阀门有限公司 | 三防漆–水性三防漆–水性浸渍漆–贝塔三防漆厂家 | 品牌策划-品牌设计-济南之式传媒广告有限公司官网-提供品牌整合丨影视创意丨公关活动丨数字营销丨自媒体运营丨数字营销 | 自动记录数据电子台秤,记忆储存重量电子桌称,设定时间记录电子秤-昆山巨天 | 洗砂机械-球磨制砂机-洗沙制砂机械设备_青州冠诚重工机械有限公司 | 老城街小面官网_正宗重庆小面加盟技术培训_特色面馆加盟|牛肉拉面|招商加盟代理费用多少钱 | 档案密集架_电动密集架_移动密集架_辽宁档案密集架-盛隆柜业厂家现货批发销售价格公道 | 珠海网站建设_响应网站建设_珠海建站公司_珠海网站设计与制作_珠海网讯互联 | 棕刚玉-白刚玉厂家价格_巩义市东翔净水材料厂 | ORP控制器_ORP电极价格-上优泰百科| 焊管生产线_焊管机组_轧辊模具_焊管设备_焊管设备厂家_石家庄翔昱机械 | 专业生产动态配料系统_饲料配料系统_化肥配料系统等配料系统-郑州鑫晟重工机械有限公司 | 塑料异型材_PVC异型材_封边条生产厂家_PC灯罩_防撞扶手_医院扶手价格_东莞市怡美塑胶制品有限公司 | 氢氧化钙设备, 氢氧化钙生产线-淄博惠琛工贸有限公司 | 河南中整光饰机械有限公司-抛光机,去毛刺抛光机,精密镜面抛光机,全自动抛光机械设备 |