如果你在大學(xué)學(xué)習(xí)過操作系統(tǒng)這門課,監(jiān)視器是操作系統(tǒng)中做同步的重要概念(額孤钦,我真沒聽過,難道翻譯過來的不一樣)纯丸。它也用于Java同步偏形。這個(gè)帖子用類比來解釋“監(jiān)視”的基本思想。
1.什么是監(jiān)視器
監(jiān)視器可以看做包含特殊事物的房間觉鼻。這個(gè)特殊房間一次只能被一個(gè)消費(fèi)者(線程)暫用俊扭。這個(gè)房間通常包含一些數(shù)據(jù)和代碼。
如果客戶想要占用這個(gè)特殊房間坠陈,他必須進(jìn)入走廊(hallWay)才能等到统扳。調(diào)度器會(huì)根據(jù)特定的算法(比如先進(jìn)先出)來選擇一個(gè)喘帚。如果它被某種原因掛起了,他將會(huì)被送到等候室咒钟,以后按照調(diào)度進(jìn)入這個(gè)特殊房間吹由。如上圖所示,這個(gè)建筑物有三個(gè)客房朱嘴。
簡(jiǎn)而言之倾鲫,監(jiān)視器是確保每次只有一個(gè)線程來訪問特定的代碼和數(shù)據(jù)的裝置。
2.它是怎么在Java中實(shí)現(xiàn)的萍嬉?
在Java虛擬機(jī)中乌昔,每個(gè)對(duì)象和類都與監(jiān)視器相關(guān)聯(lián)。為了實(shí)現(xiàn)監(jiān)視器的互斥能力壤追,鎖(有時(shí)稱為互斥)和每個(gè)對(duì)象和類相互關(guān)聯(lián)磕道。這在操作系統(tǒng)書中被稱為信號(hào)量,互斥是為二維信號(hào)量行冰。
如果一個(gè)線程擁有某些數(shù)據(jù)的鎖定溺蕉,那么其他線程將不能獲得鎖直到擁有該鎖的線程釋放它為止。如果我們?cè)诙嗑€程編程中一直操作一個(gè)信號(hào)量將不方便悼做。幸運(yùn)的Java虛擬機(jī)自動(dòng)為我們做了這些疯特。
要聲明一個(gè)監(jiān)視區(qū),意味著數(shù)據(jù)不能被多個(gè)線程訪問肛走,Java提供同步語句和同步方法漓雅。一旦代碼嵌入了synchronized關(guān)鍵字,它就是一個(gè)監(jiān)視器區(qū)域朽色。這些鎖由Java虛擬機(jī)自動(dòng)實(shí)現(xiàn)邻吞。
3.在Java的同步代碼中,哪部分是監(jiān)視器葫男?
我們知道任何一個(gè)類或?qū)ο蠖己捅O(jiān)視器綁定吃衅。我認(rèn)為每個(gè)對(duì)象都有個(gè)監(jiān)視器是很好的,因?yàn)槊總€(gè)對(duì)象可以有自己的關(guān)鍵部分(能夠見識(shí)線程序列)腾誉。
為了啟用不同的線程協(xié)作,Java提供wait()和notify()來掛起一個(gè)線程峻呕,并分別喚醒另一個(gè)在此對(duì)象等待的線程利职。另外還有三個(gè)其他版本:
wait(long timeout, int nanos)
wait(long timeout) notified by other threads or notified by timeout.
notify(all)
這些方法只能在synchronized語句或synchronized方法中調(diào)用。原因瘦癌,如果一個(gè)方法不需要互斥猪贪,那么就不需要線程之間的監(jiān)視或協(xié)作,每個(gè)線程都可以自由地訪問他們讯私。
下面是同步代碼的示例:
Reference:1. Java Doc for Object