亚洲情人网-亚洲情人-亚洲欧洲综合-亚洲欧洲自拍-欧美专区亚洲

locklock(locklock水杯)

  • 生活
  • 2023-04-21 15:43

ReentrantLock

ReentrantLock,一個(gè)可重入的互斥鎖,它具有與使用synchronized***和語(yǔ)句所訪問(wèn)的隱式監(jiān)視器鎖相同的一些基本行為和語(yǔ)義,但功能更強(qiáng)大。

ReentrantLock基本用法

先來(lái)看一下ReentrantLock的基本用法:

publicclassThreadDomain38{privateLocklock=newReentrantLock();publicvoidtestMethod(){try{lock.lock();for(inti=0;i<2;i++){System.out.println("ThreadName="+Thread.currentThread().getName()+",i="+i);}}finally{lock.unlock();}}}publicclassMyThread38extendsThread{privateThreadDomain38td;publicMyThread38(ThreadDomain38td){this.td=td;}publicvoidrun(){td.testMethod();}}publicstaticvoidmain(String[]args){ThreadDomain38td=newThreadDomain38();MyThread38mt0=newMyThread38(td);MyThread38mt1=newMyThread38(td);MyThread38mt2=newMyThread38(td);mt0.start();mt1.start();mt2.start();}

看一下運(yùn)行結(jié)果:

ThreadName=Thread-1,i=0ThreadName=Thread-1,i=1ThreadName=Thread-0,i=0ThreadName=Thread-0,i=1ThreadName=Thread-2,i=0ThreadName=Thread-2,i=1

沒(méi)有任何的交替,數(shù)據(jù)都是分組打印的,說(shuō)明了一個(gè)線程打印完畢之后下一個(gè)線程才可以獲得鎖去打印數(shù)據(jù),這也證明了ReentrantLock具有加鎖的功能

ReentrantLock持有的是對(duì)象監(jiān)視器

前面已經(jīng)證明了ReentrantLock具有加鎖功能,但我們還不知道ReentrantLock持有的是什么鎖,因此寫個(gè)例子看一下:

publicclassThreadDomain39{privateLocklock=newReentrantLock();publicvoidmethodA(){try{lock.lock();System.out.println("MethodAbeginThreadName="+Thread.currentThread().getName());Thread.sleep(5000);System.out.println("MethodAendThreadName="+Thread.currentThread().getName());}catch(InterruptedExceptione){e.printStackTrace();}finally{lock.unlock();}}publicvoidmethodB(){lock.lock();System.out.println("MethodBbeginThreadName="+Thread.currentThread().getName());System.out.println("MethodBbeginThreadName="+Thread.currentThread().getName());lock.unlock();}}

寫兩個(gè)線程分別調(diào)用methodA()和methodB()***:

publicclassMyThread39_0extendsThread{privateThreadDomain39td;publicMyThread39_0(ThreadDomain39td){this.td=td;}publicvoidrun(){td.methodA();}}publicclassMyThread39_1extendsThread{privateThreadDomain39td;publicMyThread39_1(ThreadDomain39td){this.td=td;}publicvoidrun(){td.methodB();}}

寫一個(gè)main函數(shù)啟動(dòng)這兩個(gè)線程:

publicstaticvoidmain(String[]args){ThreadDomain39td=newThreadDomain39();MyThread39_0mt0=newMyThread39_0(td);MyThread39_1mt1=newMyThread39_1(td);mt0.start();mt1.start();}

看一下運(yùn)行結(jié)果:

MethodBbeginThreadName=Thread-1MethodBbeginThreadName=Thread-1MethodAbeginThreadName=Thread-0MethodAendThreadName=Thread-0

看不見時(shí)間,不過(guò)第四確實(shí)是格了5秒左右才打印出來(lái)的。從結(jié)果來(lái)看,已經(jīng)證明了ReentrantLock持有的是對(duì)象監(jiān)視器,可以寫一段代碼進(jìn)一步證明這一結(jié)論,即去掉methodB()內(nèi)部和鎖相關(guān)的代碼,只留下兩句打印語(yǔ)句:

MethodAbeginThreadName=Thread-0MethodBbeginThreadName=Thread-1MethodBbeginThreadName=Thread-1MethodAendThreadName=Thread-0

看到交替打印了,進(jìn)一步證明了ReentrantLock持有的是"對(duì)象監(jiān)視器"的結(jié)論。

不過(guò)注意一點(diǎn),ReentrantLock雖然持有對(duì)象監(jiān)視器,但是和synchronized持有的對(duì)象監(jiān)視器不是一個(gè)意思,雖然我也不清楚兩個(gè)持有的對(duì)象監(jiān)視器有什么區(qū)別,不過(guò)把methodB()***用synchronized修飾,methodA()不變,兩個(gè)***還是異步運(yùn)行的,所以就記一個(gè)結(jié)論吧----ReentrantLock和synchronized持有的對(duì)象監(jiān)視器不同。

另外,千萬(wàn)別忘了,ReentrantLock持有的鎖是需要手動(dòng)去unlock()的

Condition

synchronized與wait()和nitofy()/notifyAll()***相結(jié)合可以實(shí)現(xiàn)等待/通知模型,ReentrantLock同樣可以,但是需要借助Condition,且Condition有更好的靈活性,具體體現(xiàn)在:

1、一個(gè)Lock里面可以創(chuàng)建多個(gè)Condition實(shí)例,實(shí)現(xiàn)多路通知

2、notify()***進(jìn)行通知時(shí),被通知的線程時(shí)Java虛擬機(jī)隨機(jī)選擇的,但是ReentrantLock結(jié)合Condition可以實(shí)現(xiàn)有選擇性地通知,這是非常重要的

看一下利用Condition實(shí)現(xiàn)等待/通知模型的最簡(jiǎn)單用法,下面的代碼注意一下,await()和signal()之前,必須要先lock()獲得鎖,使用完畢在finally中unlock()釋放鎖,這和wait()/notify()/notifyAll()使用前必須先獲得對(duì)象鎖是一樣的:

publicclassThreadDomain40{privateLocklock=newReentrantLock();privateConditioncondition=lock.newCondition();publicvoidawait(){try{lock.lock();System.out.println("await時(shí)間為:"+System.currentTimeMillis());condition.await();System.out.println("await等待結(jié)束");}catch(InterruptedExceptione){e.printStackTrace();}finally{lock.unlock();}}publicvoidsignal(){try{lock.lock();System.out.println("signal時(shí)間為:"+System.currentTimeMillis());condition.signal();}finally{lock.unlock();}}}publicclassMyThread40extendsThread{privateThreadDomain40td;publicMyThread40(ThreadDomain40td){this.td=td;}publicvoidrun(){td.await();}}publicstaticvoidmain(String[]args)throwsException{ThreadDomain40td=newThreadDomain40();MyThread40mt=newMyThread40(td);mt.start();Thread.sleep(3000);td.signal();}

看一下運(yùn)行結(jié)果:

await時(shí)間為:1443970329524signal時(shí)間為:1443970332524await等待結(jié)束

差值是3000毫秒也就是3秒,符合代碼預(yù)期,成功利用ReentrantLock的Condition實(shí)現(xiàn)了等待/通知模型。其實(shí)這個(gè)例子還證明了一點(diǎn),Condition的await()***是釋放鎖的,原因也很簡(jiǎn)單,要是await()***不釋放鎖,那么signal()***又怎么能調(diào)用到Condition的signal()***呢?

注意要是用一個(gè)Condition的話,那么多個(gè)線程被該Condition給await()后,調(diào)用Condition的signalAll()***喚醒的是所有的線程。如果想單獨(dú)喚醒部分線程該怎么辦呢?new出多個(gè)Condition就可以了,這樣也有助于提升程序運(yùn)行的效率。使用多個(gè)Condition的場(chǎng)景是很常見的,像ArrayBlockingQueue里就有。

猜你喜歡

主站蜘蛛池模板: 在线亚洲免费 | 男人天堂官方网站 | 最近中文字幕电影大全 | 亚洲一区二区在线成人 | 欧美视频在线观看一区二区 | 一区二区三区视频在线观看 | 日本视频在线免费看 | 五月天丁香婷婷综合 | a级毛片在线视频免费观看 9久视频 | 久热中文字幕在线 | 欧美日韩视频一区二区在线观看 | 国内精品视频成人一区二区 | 综合 欧美 亚洲日本 | 亚洲永久在线观看 | 中文字幕在线永久视频 | 深爱婷婷激情网 | 思99热精品久久只有精品 | 国产94在线传媒麻豆免费观看 | 久久亚洲不卡一区二区 | 自拍偷拍2 | a级日本片在线观看 | 高清性色生活片欧美在线 | 久久亚洲日本不卡一区二区 | 亚洲片在线 | 久久一区视频 | 亚洲欧美国产精品 | 久久久精品久久久久久久久久久 | 狠狠色丁香婷婷综合激情 | 色久月 | 亚洲国产小视频 | 婷婷六月久久综合丁香76 | 草综合| 亚洲精品午夜国产va久久 | 欧美色视频日本 | 夜色资源站www国产在线资源 | 日本在线不卡一区 | 国产精品一区二区在线播放 | 精品久久久久久中文字幕欧美 | 国内精品久久久久 | 国内精品 大秀视频 日韩精品 | 五月激情久久 |