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

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

Java并發編程之淺談ReentrantLock

瀏覽:6日期:2022-08-11 17:57:45
目錄一、首先看圖二、lock()跟蹤源碼2.1 非公平鎖實現2.1.1 tryAcquire(arg)2.1.2 acquireQueued(addWaiter(Node.EXCLUSIVE), arg)2.2 公平鎖實現2.2.1 tryAcquire(arg)一、首先看圖

Java并發編程之淺談ReentrantLock

二、lock()跟蹤源碼

Java并發編程之淺談ReentrantLock

這里對公平鎖和非公平鎖做了不同實現,由構造方法參數決定是否公平。

public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync();}2.1 非公平鎖實現

static final class NonfairSync extends Sync { private static final long serialVersionUID = 7316153563782823691L;final void lock() {if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread());else acquire(1); } protected final boolean tryAcquire(int acquires) {return nonfairTryAcquire(acquires); }}

代碼量很少。首先compareAndSetState(0, 1)通過CAS(期望值0,新值1,內存值stateOffset)

如果修改成功,即搶占到鎖,setExclusiveOwnerThread(Thread.currentThread());將AQS中的變量exclusiveOwnerThread設置為當前搶占到鎖的線程,也就是圖中的ThreadA。 若沒有搶占成功,證明此時鎖被占用,執行方法acquire(1);。

public final void acquire(int arg) { if (!tryAcquire(arg) &&acquireQueued(addWaiter(Node.EXCLUSIVE), arg))selfInterrupt();}

這里主要看兩個方法tryAcquire(arg)和acquireQueued(addWaiter(Node.EXCLUSIVE), arg)。當滿足if條件后,會給當前線程標記一個interrupt狀態。

2.1.1 tryAcquire(arg)

這個方法又有多個實現。這里看NonfairSync非公平鎖。

Java并發編程之淺談ReentrantLock

protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires);}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()) { int nextc = c + acquires; if (nextc < 0) // overflow throw new Error('Maximum lock count exceeded'); setState(nextc); return true; } return false; }

在這個方法中,還不死心,首先會判斷下AQS中的state是否為0,為0也就是說距離上次嘗試獲取鎖到現在準備進入隊列(雙向鏈表)中這段時間內,鎖已經被釋放,可以重新CAS嘗試獲取鎖。

如果當前鎖還是被持有狀態,就是state!=0,就會判斷,當前線程是不是當前持有鎖的線程exclusiveOwnerThread,如果是,則state+1,從這里可以看出state表示的是重入次數。

全部不滿足,返回false。

2.1.2 acquireQueued(addWaiter(Node.EXCLUSIVE), arg)

addWaiter

private Node addWaiter(Node mode) { Node node = new Node(Thread.currentThread(), mode); // Try the fast path of enq; backup to full enq on failure Node pred = tail; if (pred != null) {node.prev = pred;if (compareAndSetTail(pred, node)) { pred.next = node; return node;} } enq(node); return node;}

tryAcquire(arg)返回false,證明當前線程還是沒有獲取到鎖。那么就要進入隊列等待了,首先addWaiter方法,將當前線程封裝成一個Node,如果pred不為空,則將當前節點做鏈表的尾部插入,同時為了防止在此期間前序節點已經不在隊列中了,也會運用CAS操作來執行(期望值pred,新值node,內存值tailOffset)。

如果前序節點為空,或者在CAS時發現前序節點已經不存在了,則重新構建鏈表,將當前節點封裝的Node,加入到鏈表當中。

private Node enq(final Node node) { for (;;) {Node t = tail;if (t == null) { // Must initialize if (compareAndSetHead(new Node()))tail = head;} else { node.prev = t; if (compareAndSetTail(t, node)) {t.next = node;return t; }} }}

加入完成后,返回當前node節點,進入acquireQueued方法。

acquireQueued

final boolean acquireQueued(final Node node, int arg) { boolean failed = true; try {boolean interrupted = false;for (;;) {//獲取到當前node節點的上一個節點 final Node p = node.predecessor(); //如果當前的上個節點就是頭節點,會再次嘗試獲取鎖 if (p == head && tryAcquire(arg)) { //獲取成功,將當前節點置空,并成為新的頭節點setHead(node);//這個p已經沒用了,防止內存泄漏,直接指向null,下次GC時回收p.next = null; // help GC//不需要取消failed = false;//return false,不需要中斷當前線程return interrupted; } if (shouldParkAfterFailedAcquire(p, node) &&parkAndCheckInterrupt())interrupted = true;} } finally {if (failed) cancelAcquire(node); }}

這里是一個自旋操作,首先拿到當前線程封裝節點的上一個節點,如果滿足第一個if條件if (p == head && tryAcquire(arg)),證明上個節點為頭節點,則此時當前線程也會再次嘗試獲取鎖,獲取鎖成功,證明此時沒有別的線程在隊列中了,則將當前node清空并設置為頭節點,返回不需要中斷當前線程。

在第二個if條件中if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt())。走到這里證明當前線程不是第一個線程節點,或者沒有搶占到鎖,shouldParkAfterFailedAcquire這個方法見名知意,在搶占失敗后是否需要park阻塞,里面主要是用于清理雙向鏈表中被取消的節點線程和未被阻塞的節點線程。

private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) { int ws = pred.waitStatus;//獲取前置節點的等待狀態 if (ws == Node.SIGNAL)//前置節點的等待狀態為-1,表示前置節點在隊列中阻塞,那么當前節點也需要被阻塞在隊列中return true; if (ws > 0) {//前置節點等待狀態大于0,此前置節點已經被取消,循環遍歷清除所有已被取消的節點。do { node.prev = pred = pred.prev;} while (pred.waitStatus > 0);pred.next = node; } else {//前置節點等待狀態小于等于0,且不等于-1,也就是沒有被阻塞也沒有被取消//則將前置節點設置為阻塞狀態。compareAndSetWaitStatus(pred, ws, Node.SIGNAL); } return false;} 前置節點的等待狀態為-1,表示前置節點在隊列中阻塞,那么當前節點也需要被阻塞在隊列中 前置節點等待狀態大于0,此前置節點已經被取消,循環遍歷清除所有已被取消的節點。 前置節點等待狀態小于等于0,且不等于-1,也就是沒有被阻塞也沒有被取消。則將前置節點設置為阻塞狀態。

到這里,基于非公平鎖的實現結束。

2.2 公平鎖實現

公平鎖和樂觀鎖的區別就在于,非公平鎖acquire(1)前會先嘗試獲取鎖,公平鎖直接acquire(1)。

static final class FairSync extends Sync {private static final long serialVersionUID = -3000897897090466540L;final void lock() { acquire(1);}}2.2.1 tryAcquire(arg)

在tryAcquire中也和非公平鎖有一定的區別。在當前鎖沒有被占有時。非公平鎖不用考慮目前AQS隊列中的排隊情況,直接通過CAS嘗試獲取鎖。公平鎖會看目前隊列的狀態,再來決定是嘗試占有鎖還是在隊列中等待。

protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { 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;}

到此這篇關于Java并發編程之淺談ReentrantLock的文章就介紹到這了,更多相關Java ReentrantLock內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Java
相關文章:
主站蜘蛛池模板: 北京中创汇安科贸有限公司| 喷砂机厂家_自动喷砂机生产_新瑞自动化喷砂除锈设备 | 手术示教系统-数字化手术室系统-林之硕医疗云智能视频平台 | 网带通过式抛丸机,,网带式打砂机,吊钩式,抛丸机,中山抛丸机生产厂家,江门抛丸机,佛山吊钩式,东莞抛丸机,中山市泰达自动化设备有限公司 | 盘式曝气器-微孔曝气器-管式曝气器-曝气盘-斜管填料 | 郑州市前程水处理有限公司 | 高压管道冲洗清洗机_液压剪叉式升降机平台厂家-林君机电 | 交流伺服电机|直流伺服|伺服驱动器|伺服电机-深圳市华科星电气有限公司 | 免费分销系统 — 分销商城系统_分销小程序开发 -【微商来】 | NMRV减速机|铝合金减速机|蜗轮蜗杆减速机|NMRV减速机厂家-东莞市台机减速机有限公司 | 芝麻黑-芝麻黑石材厂家-永峰石业 | 高压无油空压机_无油水润滑空压机_水润滑无油螺杆空压机_无油空压机厂家-科普柯超滤(广东)节能科技有限公司 | 无线讲解器-导游讲解器-自助讲解器-分区讲解系统 品牌生产厂家[鹰米讲解-合肥市徽马信息科技有限公司] | 对照品_中药对照品_标准品_对照药材_「格利普」高纯中药标准品厂家-成都格利普生物科技有限公司 澳门精准正版免费大全,2025新澳门全年免费,新澳天天开奖免费资料大全最新,新澳2025今晚开奖资料,新澳马今天最快最新图库 | 新密高铝耐火砖,轻质保温砖价格,浇注料厂家直销-郑州荣盛窑炉耐火材料有限公司 | 特种阀门-调节阀门-高温熔盐阀-镍合金截止阀-钛阀门-高温阀门-高性能蝶阀-蒙乃尔合金阀门-福建捷斯特阀门制造有限公司 | 防爆电机_防爆电机型号_河南省南洋防爆电机有限公司 | 光伏家 - 太阳能光伏发电_分布式光伏发电_太阳能光伏网 | 冲锋衣滑雪服厂家-冲锋衣定制工厂-滑雪服加工厂-广东睿牛户外(S-GERT) | 大型多片锯,圆木多片锯,方木多片锯,板材多片锯-祥富机械有限公司 | 粘度计维修,在线粘度计,二手博勒飞粘度计维修|收购-天津市祥睿科技有限公司 | 高低温万能试验机_拉力试验机_拉伸试验机-馥勒仪器科技(上海)有限公司 | 汽液过滤网厂家_安平县银锐丝网有限公司 | 东莞市海宝机械有限公司-不锈钢分选机-硅胶橡胶-生活垃圾-涡电流-静电-金属-矿石分选机 | 菏泽商标注册_菏泽版权登记_商标申请代理_菏泽商标注册去哪里 | 济南侦探调查-济南调查取证-山东私家侦探-山东白豹调查咨询公司 密集架|电动密集架|移动密集架|黑龙江档案密集架-大量现货厂家销售 | 蒸汽吸附分析仪-进口水分活度仪|康宝百科| 台湾阳明固态继电器-奥托尼克斯光电传感器-接近开关-温控器-光纤传感器-编码器一级代理商江苏用之宜电气 | 橡胶接头_橡胶软接头_可曲挠橡胶接头-巩义市创伟机械制造有限公司 | 帽子厂家_帽子工厂_帽子定做_义乌帽厂_帽厂_制帽厂_帽子厂_浙江高普制帽厂 | 山东锐智科电检测仪器有限公司_超声波测厚仪,涂层测厚仪,里氏硬度计,电火花检漏仪,地下管线探测仪 | 安徽净化工程设计_无尘净化车间工程_合肥净化实验室_安徽创世环境科技有限公司 | 除尘布袋_液体过滤袋_针刺毡滤料-杭州辉龙过滤技术有限公司 | 北京网站建设公司_北京网站制作公司_北京网站设计公司-北京爱品特网站建站公司 | 营养师网,营养师考试时间,报名入口—网站首页 | 视觉检测设备_自动化检测设备_CCD视觉检测机_外观缺陷检测-瑞智光电 | 高楼航空障碍灯厂家哪家好_航空障碍灯厂家_广州北斗星障碍灯有限公司 | 水篦子|雨篦子|镀锌格栅雨水篦子|不锈钢排水篦子|地下车库水箅子—安平县云航丝网制品厂 | 上海盐水喷雾试验机_两厢式冷热冲击试验箱-巨怡环试 | 净化板-洁净板-净化板价格-净化板生产厂家-山东鸿星新材料科技股份有限公司 | 泰安办公家具-泰安派格办公用品有限公司 | 高柔性拖链电缆-聚氨酯卷筒电缆-柔性屏蔽电缆厂家-玖泰电缆 |