一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - java的Object里wait()實現(xiàn)原理講解

java的Object里wait()實現(xiàn)原理講解

2022-01-20 00:59ZytheMoon Java教程

這篇文章主要介紹了java的Object里wait()實現(xiàn)原理,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

Object中的wait()實現(xiàn)原理

在進行wait()之前,就代表著需要爭奪Synchorized,而Synchronized代碼塊通過javap生成的字節(jié)碼中包含monitorenter和monitorexit兩個指令。

當在進加鎖的時候會執(zhí)行monitorenter指令,執(zhí)行該指令可以獲取對象的monitor。同時在執(zhí)行Lock.wait()的時候也必須持有monitor對象。

在多核環(huán)境下,多個線程有可能同時執(zhí)行monitorenter指令,并獲取lock對象關聯(lián)的monitor,但只有一個線程可以和monitor建立關聯(lián),這個線程執(zhí)行到wait方法時,wait方法會將當前線程放入wait set,使其進行等待直到被喚醒,并放棄lock對象上的所有同步聲明,意味著該線程釋放了鎖,其他線程可以重新執(zhí)行加鎖操作,notify方法會選擇wait set中任意一個線程進行喚醒,notifyAll方法會喚醒monitor的wait set中所有線程。執(zhí)行完notify方法并不會立馬喚醒等待線程。那么wait具體是怎么實現(xiàn)的呢?

首先在HotSpot虛擬機中,monitor采用ObjectMonitor實現(xiàn),每個線程都具有兩個隊列,分別為free和used,用來存放ObjectMonitor。如果當前free列表為空,線程將向全局global list請求分配ObjectMonitor。

ObjectMonitor對象中有兩個隊列,都用來保存ObjectWaiter對象,分別是_WaitSet 和 _EntrySet。_owner用來指向獲得ObjectMonitor對象的線程

ObjectWaiter對象是雙向鏈表結構,保存了_thread(當前線程)以及當前的狀態(tài)TState等數(shù)據(jù), 每個等待鎖的線程都會被封裝成ObjectWaiter對象。

java的Object里wait()實現(xiàn)原理講解

  • _WaitSet:處于wait狀態(tài)的線程,會被加入到wait set;
  • _EntrySett:處于等待鎖block狀態(tài)的線程,會被加入到entry set;

wait方法實現(xiàn)

lock.wait()方法最終通過ObjectMonitor的 wait(jlong millis, bool interruptable, TRAPS)實現(xiàn)

1、將當前線程封裝成ObjectWaiter對象node

2、通過ObjectMonitor::AddWaiter方法將node添加到_WaitSet列表中

3、通過ObjectMonitor::exit方法釋放當前的ObjectMonitor對象,這樣其它競爭線程就可以獲取該ObjectMonitor對象

4、最終底層的park方法會掛起線程

ObjectSynchorizer::wait方法通過Object對象找到ObjectMonitor對象來調用方法 ObjectMonitor::wait(),通過調用ObjectMonitor::AddWaiter()可以把新建的ObjectWaiter對象,放入到_WaitSet隊列的末尾,然后在ObjectMonitor::exit釋放鎖,接著通過執(zhí)行thread_ParkEvent->park來掛起線程,也就是進行wait。

Object對象中的wait,notify,notifyAll的理解

wait,notify,notifyAll 是定義在Object類的實例方法,用于控制線程狀態(tài),在線程協(xié)作時,大家都會用到notify()或者notifyAll()方法,其中wait與notify是java同步機制中重要的組成部分,需要結合與synchronized關鍵字才能使用,在調用一個Object的wait與notify/notifyAll的時候,必須保證調用代碼對該Object是同步的,也就是說必須在作用等同于synchronized(object){......}的內(nèi)部才能夠去調用obj的wait與notify/notifyAll三個方法,否則就會報錯:java.lang.IllegalMonitorStateException:current thread not owner(意思是因為沒有同步,所以線程對對象鎖的狀態(tài)是不確定的,不能調用這些方法)。

wait的目的就在于暴露出對象鎖,所以需要保證在lock的同步代碼中調用lock.wait()方法,讓其他線程可以通過對象的notify叫醒等待在該對象的等該池里的線程。同樣notify也會釋放對象鎖,在調用之前必須獲得對象的鎖,不然也會報異常。所以,在線程自動釋放其占有的對象鎖后,不會去申請對象鎖,只有當線程被喚醒的時候或者達到最大的睡眠時間,它才再次爭取對象鎖的權利

主要方法:

(1).wait()

等待對象的同步鎖,需要獲得該對象的同步鎖才可以調用這個方法,否則編譯可以通過,但運行時會收到一個異常:IllegalMonitorStateException。調用任意對象的 wait() 方法導致該線程阻塞,該線程不可繼續(xù)執(zhí)行,并且該對象上的鎖被釋放。

(2).notify()

喚醒在等待該對象同步鎖的線程(只喚醒一個,如果有多個在等待),注意的是在調用此方法的時候,并不能確切的喚醒某一個等待狀態(tài)的線程,而是由JVM確定喚醒哪個線程,而且不是按優(yōu)先級。調用任意對象的notify()方法則導致因調用該對象的 wait()方法而阻塞的線程中隨機選擇的一個解除阻塞(但要等到獲得鎖后才真正可執(zhí)行)。

(3).notifyAll()

喚醒所有等待的線程,注意喚醒的是notify之前wait的線程,對于notify之后的wait線程是沒有效果的。

通過一個實例來看一下實際的效果,開啟兩個線和,一個線程 打印1到52的數(shù)字,一個打印A到Z的字母,要求,打印兩個數(shù),打印一個字母,這樣交替順序打印,代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/**
 * create by spy on 2018/6/4
 */
public class ShuZiZiMuThread {
    public static void main(String[] args) {
        Object object = new Object();
        shuzi shuzi = new shuzi(object);
        zimu zimu = new zimu(object);
        Thread t = new Thread(shuzi);
        t.setName("shuzi");
        Thread t1 = new Thread(zimu);
        t1.setName("zimu");
        t.start();//數(shù)字線程先運行
        t1.start();
    }
}
class shuzi implements Runnable{
    private Object object;
    //聲明類的引用
    public shuzi(Object object) {
        this.object = object;
    }
    public void run() {
        synchronized (object) {//上鎖
            for(int i=1;i<53;i++){
                System.out.print(i+",");
                if(i%2==0){
                    object.notifyAll();//喚醒其它爭奪權限的線程
                    try {
                        object.wait();//釋放鎖,進入等待
                        System.out.println("數(shù)字打印類打全打印當前對象擁有對象鎖的線程"+Thread.currentThread().getName());//輸出當前擁有鎖的線程名稱
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}
class zimu implements Runnable{
    private Object object;
    public zimu(Object object) {
        this.object = object;
    }
    public void run() {
        synchronized (object) {
            for(int j=65;j<91;j++){
                char c = (char)j;
                System.out.print(c);
                object.notifyAll();//喚醒其它爭奪權限的線程
                try {
                    object.wait();//釋放鎖,進入等待
                    System.out.println("字母打印類打全打印當前對象擁有對象鎖的線程"+Thread.currentThread().getName());//輸出當前擁有鎖的線程名稱
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

實際運行的結果 :

1,2,A數(shù)字打印類打印當前對象擁有對象鎖的線程shuzi
3,4,字母打印類打印當前對象擁有對象鎖的線程zimu
B數(shù)字打印類打印當前對象擁有對象鎖的線程shuzi
5,6,字母打印類打印當前對象擁有對象鎖的線程zimu
C數(shù)字打印類打印當前對象擁有對象鎖的線程shuzi
7,8,字母打印類打印當前對象擁有對象鎖的線程zimu
D數(shù)字打印類打印當前對象擁有對象鎖的線程shuzi
9,10,字母打印類打印當前對象擁有對象鎖的線程zimu
E數(shù)字打印類打印當前對象擁有對象鎖的線程shuzi
11,12,字母打印類打印當前對象擁有對象鎖的線程zimu
F數(shù)字打印類打印當前對象擁有對象鎖的線程shuzi
13,14,字母打印類打印當前對象擁有對象鎖的線程zimu
G數(shù)字打印類打印當前對象擁有對象鎖的線程shuzi
15,16,字母打印類打印當前對象擁有對象鎖的線程zimu
H數(shù)字打印類打印當前對象擁有對象鎖的線程shuzi
17,18,字母打印類打印當前對象擁有對象鎖的線程zimu
I數(shù)字打印類打印當前對象擁有對象鎖的線程shuzi
19,20,字母打印類打印當前對象擁有對象鎖的線程zimu
J數(shù)字打印類打印當前對象擁有對象鎖的線程shuzi
21,22,字母打印類打印當前對象擁有對象鎖的線程zimu
K數(shù)字打印類打印當前對象擁有對象鎖的線程shuzi
23,24,字母打印類打印當前對象擁有對象鎖的線程zimu
L數(shù)字打印類打印當前對象擁有對象鎖的線程shuzi
25,26,字母打印類打印當前對象擁有對象鎖的線程zimu
M數(shù)字打印類打印當前對象擁有對象鎖的線程shuzi
27,28,字母打印類打印當前對象擁有對象鎖的線程zimu
N數(shù)字打印類打印當前對象擁有對象鎖的線程shuzi
29,30,字母打印類打印當前對象擁有對象鎖的線程zimu
O數(shù)字打印類打印當前對象擁有對象鎖的線程shuzi
31,32,字母打印類打印當前對象擁有對象鎖的線程zimu
P數(shù)字打印類打印當前對象擁有對象鎖的線程shuzi
33,34,字母打印類打印當前對象擁有對象鎖的線程zimu
Q數(shù)字打印類打印當前對象擁有對象鎖的線程shuzi
35,36,字母打印類打印當前對象擁有對象鎖的線程zimu
R數(shù)字打印類打印當前對象擁有對象鎖的線程shuzi
37,38,字母打印類打印當前對象擁有對象鎖的線程zimu
S數(shù)字打印類打印當前對象擁有對象鎖的線程shuzi
39,40,字母打印類打印當前對象擁有對象鎖的線程zimu
T數(shù)字打印類打印當前對象擁有對象鎖的線程shuzi
41,42,字母打印類打印當前對象擁有對象鎖的線程zimu
U數(shù)字打印類打印當前對象擁有對象鎖的線程shuzi
43,44,字母打印類打印當前對象擁有對象鎖的線程zimu
V數(shù)字打印類打印當前對象擁有對象鎖的線程shuzi
45,46,字母打印類打印當前對象擁有對象鎖的線程zimu
W數(shù)字打印類打印當前對象擁有對象鎖的線程shuzi
47,48,字母打印類打印當前對象擁有對象鎖的線程zimu
X數(shù)字打印類打印當前對象擁有對象鎖的線程shuzi
49,50,字母打印類打印當前對象擁有對象鎖的線程zimu
Y數(shù)字打印類打印當前對象擁有對象鎖的線程shuzi
51,52,字母打印類打印當前對象擁有對象鎖的線程zimu
Z數(shù)字打印類打印當前對象擁有對象鎖的線程shuzi

結果分析:

通過結果可以看出:

在字母打一打印類里 調用完

?
1
2
3
4
object.notifyAll();//喚醒其它爭奪權限的線程
object.wait();//釋放鎖,進入等待后,擁有對象鎖的線程是shuzi在數(shù)字打印類里 調用完
object.notifyAll();//喚醒其它爭奪權限的線程
object.wait();//釋放鎖,進入等待后,擁有對象鎖的線程是zimu

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/ZytheMoon/article/details/89461016

延伸 · 閱讀

精彩推薦
  • Java教程Java BufferWriter寫文件寫不進去或缺失數(shù)據(jù)的解決

    Java BufferWriter寫文件寫不進去或缺失數(shù)據(jù)的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進去或缺失數(shù)據(jù)的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程Java實現(xiàn)搶紅包功能

    Java實現(xiàn)搶紅包功能

    這篇文章主要為大家詳細介紹了Java實現(xiàn)搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發(fā)項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關于小米推送Java代碼,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩(wěn)中求8032021-07-12
  • Java教程xml與Java對象的轉換詳解

    xml與Java對象的轉換詳解

    這篇文章主要介紹了xml與Java對象的轉換詳解的相關資料,需要的朋友可以參考下...

    Java教程網(wǎng)2942020-09-17
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發(fā)現(xiàn)了對于集合操作轉換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關于Java8中S...

    阿杜7482021-02-04
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經(jīng)有好久沒有升過級了。升級完畢重啟之后,突然發(fā)現(xiàn)好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
主站蜘蛛池模板: 嫩草在线观看视频 | 免费观看一级特黄三大片视频 | 91精品国产亚洲爽啪在线影院 | 摸逼小说| 操一操影院 | 国产成人精品三级在线 | 亚洲色图欧美图片 | 国产一区二区三区毛片 | 国精视频一区二区视频 | 免费观看在线观看 | 人与禽交3d动漫羞羞动漫 | 亚洲日韩精品欧美一区二区一 | 亚洲国产精品久久卡一 | 男人把大ji巴放进男人免费视频 | xxx95日本老师xxx学生 | 国产香蕉国产精品偷在线观看 | 亚洲第一页综合 | 青青草国产精品久久碰 | 国产亚洲高清国产拍精品 | 护士被多人调教到失禁h | 小sao货ji巴cao死你视频 | 成人伊人亚洲人综合网站222 | 无套大战白嫩乌克兰美女 | 午夜视频网站 | 啾咪成人漫画免费 | 国产清纯91天堂在线观看 | 成人在线一区二区 | 消息称老熟妇乱视频一区二区 | 美女被视频网站看免费入口 | 亚洲va国产日韩欧美精品色婷婷 | 91精品久久一区二区三区 | 国产a一级毛片爽爽影院 | 四虎4hu永久免费国产精品 | 吃胸膜奶视频456 | 国产综合网站 | 逼逼流水了 | 国内自拍网红在线综合 | 美女的让男人桶爽免费看 | 午夜影院c绿象 | 乌克兰一级毛片 | ffee性xxⅹ另类老妇hd |