日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

并发学习笔记 (5)

發(fā)布時(shí)間:2025/3/20 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 并发学习笔记 (5) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

tutorials site

Locks in java

Locks (and other more advanced synchronization mechanisms) are created using synchronized blocks, so it is not like we can get totally rid of the synchronized keyword.
鎖的實(shí)現(xiàn)是利用synchonized, wait(),notify()方法實(shí)現(xiàn)的。所以不可以認(rèn)為鎖可以完全脫離synchonized實(shí)現(xiàn)。

Java包 JUC java.util.concurrent.locks 包括了很多l(xiāng)ock接口的實(shí)現(xiàn)了類(lèi),這些類(lèi)足夠使用。
但是需要知道如何使用它們,以及這些類(lèi)背后的理論。JUC包教程

用synchonized:可以保證在同一時(shí)間只有一個(gè)線程可以執(zhí)行 return ++count:

public class Counter{private int count = 0;public int inc(){synchronized(this){return ++count;}} }

以下的Counter類(lèi)用Lock代替synchronized 達(dá)到同樣的目的:
lock() 方法會(huì)對(duì) Lock 實(shí)例對(duì)象進(jìn)行加鎖,因此所有其他對(duì)該對(duì)象調(diào)用 lock() 方法的線程都會(huì)被阻塞,直到該 Lock 對(duì)象的 unlock() 方法被調(diào)用。

public class Counter{private Lock lock = new Lock();private int count = 0;public int inc(){lock.lock();int newCount = ++count;lock.unlock();return newCount;} }

那么問(wèn)題來(lái)了, Lock類(lèi)是怎么設(shè)計(jì)的?


Lock 類(lèi)的設(shè)計(jì)

一個(gè)Lock類(lèi)的簡(jiǎn)單實(shí)現(xiàn):

javapublic class Lock{private boolean isLocked = false;public synchronized void lock() throws InterruptedException{while(isLocked){wait();}isLocked = true;}public synchronized void unlock(){isLocked = false;notify();} }

while(isLocked) 循環(huán), 又被稱(chēng)為spin lock自旋鎖。當(dāng) isLocked 為 true 時(shí),調(diào)用 lock() 的線程在 wait() 調(diào)用上阻塞等待。為防止該線程沒(méi)有收到 notify() 調(diào)用也從 wait() 中返回(也稱(chēng)作虛假喚醒),這個(gè)線程會(huì)重新去檢查 isLocked 條件以決定當(dāng)前是否可以安全地繼續(xù)執(zhí)行還是需要重新保持等待,而不是認(rèn)為線程被喚醒了就可以安全地繼續(xù)執(zhí)行了。如果 isLocked 為 false,當(dāng)前線程會(huì)退出 while(isLocked) 循環(huán),并將 isLocked 設(shè)回 true,讓其它正在調(diào)用 lock() 方法的線程能夠在 Lock 實(shí)例上加鎖。

當(dāng)線程完成了臨界區(qū)(位于 lock() 和 unlock() 之間)中的代碼,就會(huì)調(diào)用 unlock()。執(zhí)行 unlock() 會(huì)重新將 isLocked 設(shè)置為 false,并且通知(喚醒)其中一個(gè)(若有的話)在 lock() 方法中調(diào)用了 wait() 函數(shù)而處于等待狀態(tài)的線程。

鎖的可重入性

synchronized 同步塊是可重入的。這意味著: 如果一個(gè)java線程進(jìn)入了代碼中的同步塊synchonzied block,并因此獲得了該同步塊使用的同步對(duì)象對(duì)應(yīng)的管程monitor object上的鎖那么這個(gè)線程可以進(jìn)入由同一個(gè)管程對(duì)象所同步的另一個(gè) java 代碼塊

前面的Lock的設(shè)計(jì)就不是可重入的:

javapublic class Reentrant2{Lock lock = new Lock();public outer(){lock.lock();inner();lock.unlock();}public synchronized inner(){lock.lock();//do somethinglock.unlock();} }

一個(gè)線程是否被允許退出 lock() 方法是由 while 循環(huán)(自旋鎖)中的條件決定的。當(dāng)前的判斷條件是只有當(dāng) isLocked 為 false 時(shí) lock 操作才被允許,而沒(méi)有考慮是哪個(gè)線程鎖住了它。
所以需要對(duì)Lock的設(shè)計(jì)做出如下修改,才能可重入。

javapublic class Lock{boolean isLocked = false;Thread lockedBy = null;int lockedCount = 0;public synchronized void lock()throws InterruptedException{Thread callingThread =Thread.currentThread();while(isLocked && lockedBy != callingThread){wait();}isLocked = true;lockedCount++;lockedBy = callingThread;}public synchronized void unlock(){if(Thread.curentThread() ==this.lockedBy){lockedCount--;if(lockedCount == 0){isLocked = false;notify();}}}... }

注意到現(xiàn)在的 while 循環(huán)(自旋鎖)也考慮到了已鎖住該 Lock 實(shí)例的線程。如果當(dāng)前的鎖對(duì)象沒(méi)有被加鎖 (isLocked = false),或者當(dāng)前調(diào)用線程已經(jīng)對(duì)該 Lock 實(shí)例加了鎖,那么 while 循環(huán)就不會(huì)被執(zhí)行,調(diào)用 lock() 的線程就可以退出該方法(譯者注:“被允許退出該方法” 在當(dāng)前語(yǔ)義下就是指不會(huì)調(diào)用 wait() 而導(dǎo)致阻塞)。

除此之外,我們需要記錄同一個(gè)線程重復(fù)對(duì)一個(gè)鎖對(duì)象加鎖的次數(shù)。否則,一次 unblock() 調(diào)用就會(huì)解除整個(gè)鎖,即使當(dāng)前鎖已經(jīng)被加鎖過(guò)多次。在 unlock() 調(diào)用沒(méi)有達(dá)到對(duì)應(yīng) lock() 調(diào)用的次數(shù)之前,我們不希望鎖被解除。

現(xiàn)在這個(gè) Lock 類(lèi)就是可重入的了。

鎖的公平性

Starvation and Fairness 饑餓和公平

一個(gè)線程因?yàn)槠渌€程長(zhǎng)期占有CPU而自己獲得不到,這種狀態(tài)稱(chēng)為Starvation. 解決線程饑餓的方法是公平機(jī)制fairness公平機(jī)制,讓所有線程都能公平的有機(jī)會(huì)去獲得CPU。

導(dǎo)致饑餓的原因

  • 高優(yōu)先級(jí)的線程占有了所有CPU處理時(shí)間,這樣低優(yōu)先級(jí)的線程獲得不到;
  • 處于阻塞狀態(tài)的線程無(wú)限期被阻塞
    Java 的同步代碼區(qū)也是一個(gè)導(dǎo)致饑餓的因素。Java 的同步代碼區(qū)對(duì)哪個(gè)線程允許進(jìn)入的次序沒(méi)有任何保障。這就意味著理論上存在一個(gè)試圖進(jìn)入該同步區(qū)的線程處于被永久堵塞的風(fēng)險(xiǎn),因?yàn)槠渌€程總是能持續(xù)地先于它獲得訪問(wèn),這即是 “饑餓” 問(wèn)題,而一個(gè)線程被 “饑餓致死” 正是因?yàn)樗貌坏?CPU 運(yùn)行時(shí)間的機(jī)會(huì)
  • Java's synchronized code blocks can be another cause of starvation.

  • 處于等待狀態(tài)的對(duì)象無(wú)限期等待
    如果多個(gè)線程處在 wait() 方法執(zhí)行上,而對(duì)其調(diào)用 notify() 不會(huì)保證哪一個(gè)線程會(huì)獲得喚醒,任何線程都有可能處于繼續(xù)等待的狀態(tài)。因此存在這樣一個(gè)風(fēng)險(xiǎn):一個(gè)等待線程從來(lái)得不到喚醒,因?yàn)槠渌却€程總是能被獲得喚醒。
  • 這里細(xì)說(shuō)一下:多線程通過(guò)共享一個(gè)object對(duì)象,來(lái)調(diào)用對(duì)象的wait/notifyAll 來(lái)導(dǎo)致線程等待或者喚醒; 每次一個(gè)線程進(jìn)入同步塊,其他所有線程陷入等待狀態(tài);然后active線程調(diào)用notifyALL()函數(shù)喚醒所有等待線程,所有線程競(jìng)爭(zhēng),只有一個(gè)線程競(jìng)爭(zhēng)成功,獲得CPU執(zhí)行。競(jìng)爭(zhēng)失敗的線程處于就緒狀態(tài),長(zhǎng)期競(jìng)爭(zhēng)失敗的線程就會(huì)饑餓。

    線程之間的對(duì)資源(object)競(jìng)爭(zhēng)導(dǎo)致的饑餓,為了避免競(jìng)爭(zhēng),所以想辦法一次喚醒一個(gè)線程。也就是下面講的FairLock 公平鎖機(jī)制。

    Implementing Fairness in Java

    使用鎖lock來(lái)代替同步塊synchonized block

    每一個(gè)調(diào)用 lock() 的線程都會(huì)進(jìn)入一個(gè)隊(duì)列,當(dāng)解鎖后,只有隊(duì)列里的第一個(gè)線程 (隊(duì)首)被允許鎖住 Fairlock 實(shí)例,所有其它的線程都將處于等待狀態(tài),直到他們處于隊(duì)列頭部。
    公平鎖實(shí)現(xiàn)機(jī)制:為每一個(gè)線程創(chuàng)建一個(gè)專(zhuān)屬鎖對(duì)象(而非多個(gè)線程共享一個(gè)對(duì)象,來(lái)wait/notify()),然后用一個(gè)隊(duì)列來(lái)管理這些鎖對(duì)象,嘗試加鎖的線程會(huì)在各自的對(duì)象上等待,當(dāng)一個(gè)線程unlock的時(shí)候,只通知隊(duì)列頭的鎖對(duì)象,以喚醒其對(duì)應(yīng)的線程

    為了讓這個(gè) Lock 類(lèi)具有可重入性,我們需要對(duì)它做一點(diǎn)小的改動(dòng):

    javapublic class FairLock {private boolean isLocked = false;private Thread lockingThread = null;private List<QueueObject> waitingThreads =new ArrayList<QueueObject>();public void lock() throws InterruptedException{QueueObject queueObject = new QueueObject();boolean isLockedForThisThread = true;synchronized(this){waitingThreads.add(queueObject);}while(isLockedForThisThread){synchronized(this){isLockedForThisThread =isLocked || waitingThreads.get(0) != queueObject;if(!isLockedForThisThread){isLocked = true;waitingThreads.remove(queueObject);lockingThread = Thread.currentThread();return;}}try{queueObject.doWait();}catch(InterruptedException e){synchronized(this) { waitingThreads.remove(queueObject); }throw e;}}}public synchronized void unlock(){if(this.lockingThread != Thread.currentThread()){throw new IllegalMonitorStateException("Calling thread has not locked this lock");}isLocked = false;lockingThread = null;if(waitingThreads.size() > 0){waitingThreads.get(0).doNotify();}} }

    總結(jié)

    以上是生活随笔為你收集整理的并发学习笔记 (5)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 欧美一区免费 | 黄色片网站在线播放 | 91传媒网站 | 啦啦啦av | 91视频网页 | 欧美性生活一区二区三区 | 嫩草一区二区三区 | 四虎福利视频 | 亚州精品国产精品乱码不99按摩 | 在线观看免费视频 | www.黄在线观看 | 日本在线视频一区二区三区 | 成人在线视频免费观看 | 中文字幕国产视频 | 岛国大片在线 | 99视频免费在线观看 | 乖女从小调教h尿便器小说 欧美韩一区二区 | 亚洲深夜在线 | 妹子干综合网 | 精品国产鲁一鲁一区二区张丽 | 久久夜色精品国产欧美乱 | 午夜看片网站 | 少妇av一区二区三区无码 | 精品人妻无码一区二区三区蜜桃一 | 韩国美女一区二区 | 黄色777 | 岛国av免费观看 | 性xxxx另类xxⅹ | 色综合久久久 | 亚洲二区在线播放视频 | 成人久久久 | 98久久| 成人字幕 | 超级黄色录像 | 国产人妻精品午夜福利免费 | 国产国产精品 | 免费黄色网址视频 | 日韩精品一区二区三区电影 | av成人毛片| 国产精品丝袜在线观看 | 国产亚洲色婷婷久久99精品 | 成人三级黄色片 | 久色综| 日本阿v视频在线观看 | 欧美资源站| 欧美xxxxxx片免费播放软件 | 国产人妖ts重口系列网站观看 | 国产99久久久国产精品 | 欧美一级黄色片视频 | 好男人在线观看 | 性xxxxxxxxx| 久久高清免费 | 亚洲图片综合网 | 亚洲第5页 | 国产大片中文字幕在线观看 | 五月天色站| 欧美在线视频观看 | 天堂网av在线 | 日韩国产在线播放 | 亚洲精品在线一区二区 | 日韩欧美三级在线 | 337p日本大胆噜噜噜鲁 | xxxx日韩| 天天久久久 | 国产黄频在线观看 | 日韩第九页 | 成人动漫在线观看免费 | 在线视频综合网 | 欧美午夜精品久久久久免费视 | 性色在线| www.四虎精品 | 激情婷婷丁香 | 黄色的网站在线 | 欧美日韩综合精品 | 嫩草午夜少妇在线影视 | 激情四射av | 91夜色视频 | 中文字字幕在线 | 污视频网站在线播放 | 自拍毛片| 在线观看日本中文字幕 | 伊人成人动漫 | wwwxx国产 | 黄色高清在线观看 | 日韩欧美在线看 | 爱情岛论坛亚洲入口 | 草草草av| 久久成人亚洲 | 91漂亮少妇露脸在线播放 | 久久香焦| 中文字幕人妻一区二区在线视频 | 亚洲中文无码av在线 | 青青国产 | 久久久极品 | 日本一级淫片色费放 | xxxxx国产| 九九国产 | 久久久久成人精品免费播放动漫 | 葵司有码中文字幕二三区 |