synchronized 除了象上面講的放在對(duì)象前面限制一段代碼的執(zhí)行外,還可以放在方法聲明中,表示整個(gè)方法為同步方法。
public synchronized void push(char c){
…
}
如果synchronized用在類聲明中,則表明該類中的所有方法都是synchronized的。
6.2.2多線程的同步
本節(jié)將討論如何控制互相交互的線程之間的運(yùn)行進(jìn)度,即多線程之間的同步問(wèn)題,下面我們將通過(guò)多線程同步的模型: 生產(chǎn)者-消費(fèi)者問(wèn)題來(lái)說(shuō)明怎樣實(shí)現(xiàn)多線程的同步。
我們把系統(tǒng)中使用某類資源的線程稱為消費(fèi)者,產(chǎn)生或釋放同類資源的線程稱為生產(chǎn)者。
在下面的Java的應(yīng)用程序中,生產(chǎn)者線程向文件中寫數(shù)據(jù),消費(fèi)者從文件中讀數(shù)據(jù),這樣,在這個(gè)程序中同時(shí)運(yùn)行的兩個(gè)線程共享同一個(gè)文件資源。通過(guò)這個(gè)例子我們來(lái)了解怎樣使它們同步。
類Producer是生產(chǎn)者模型,其中的 run()方法中定義了生產(chǎn)者線程所做的操作,循環(huán)調(diào)用push()方法,將生產(chǎn)的20個(gè)字母送入堆棧中,每次執(zhí)行完push操作后,調(diào)用sleep()方法睡眠一段隨機(jī)時(shí)間,以給其他線程執(zhí)行的機(jī)會(huì)。類Consumer是消費(fèi)者模型,循環(huán)調(diào)用pop()方法,從堆棧中取出一個(gè)數(shù)據(jù),一共取20次,每次執(zhí)行完pop操作后,調(diào)用sleep()方法睡眠一段隨機(jī)時(shí)間,以給其他線程執(zhí)行的機(jī)會(huì)。
程序執(zhí)行結(jié)果
Produced:V
Consumed:V
Produced:E
Consumed:E
Produced:P
Produced:L
...
Consumed:L
Consumed:P
在上述的例子中,通過(guò)運(yùn)用wait()和notify()方法來(lái)實(shí)現(xiàn)線程的同步,在同步中還會(huì)用到notifyAll()方法,一般來(lái)說(shuō),每個(gè)共享對(duì)象的互斥鎖存在兩個(gè)隊(duì)列,一個(gè)是鎖等待隊(duì)列,另一個(gè)是鎖申請(qǐng)隊(duì)列,鎖申請(qǐng)隊(duì)列中的第一個(gè)線程可以對(duì)該共享對(duì)象進(jìn)行操作,而鎖等待隊(duì)列中的線程在某些情況下將移入到鎖申請(qǐng)隊(duì)列。下面比較一下wait()、notify()和notifyAll()方法:
(1) wait,nofity,notifyAll必須在已經(jīng)持有鎖的情況下執(zhí)行,所以它們只能出現(xiàn)在synchronized作用的范圍內(nèi),也就是出現(xiàn)在用 synchronized修飾的方法或類中。
(2) wait的作用:釋放已持有的鎖,進(jìn)入等待隊(duì)列. 來(lái)源:www.examda.com
(3) notify的作用:喚醒wait隊(duì)列中的第一個(gè)線程并把它移入鎖申請(qǐng)隊(duì)列.
(4) notifyAll的作用:喚醒wait隊(duì)列中的所有的線程并把它們移入鎖申請(qǐng)隊(duì)列.
注意:
1) suspend()和resume()
在JDK1.2中不再使用suspend()和resume(),其相應(yīng)功能由wait()和notify()來(lái)實(shí)現(xiàn)。
2) stop()
在JDK1.2中不再使用stop(),而是通過(guò)標(biāo)志位來(lái)使程序正常執(zhí)行完畢。
public synchronized void push(char c){
…
}
如果synchronized用在類聲明中,則表明該類中的所有方法都是synchronized的。
6.2.2多線程的同步
本節(jié)將討論如何控制互相交互的線程之間的運(yùn)行進(jìn)度,即多線程之間的同步問(wèn)題,下面我們將通過(guò)多線程同步的模型: 生產(chǎn)者-消費(fèi)者問(wèn)題來(lái)說(shuō)明怎樣實(shí)現(xiàn)多線程的同步。
我們把系統(tǒng)中使用某類資源的線程稱為消費(fèi)者,產(chǎn)生或釋放同類資源的線程稱為生產(chǎn)者。
在下面的Java的應(yīng)用程序中,生產(chǎn)者線程向文件中寫數(shù)據(jù),消費(fèi)者從文件中讀數(shù)據(jù),這樣,在這個(gè)程序中同時(shí)運(yùn)行的兩個(gè)線程共享同一個(gè)文件資源。通過(guò)這個(gè)例子我們來(lái)了解怎樣使它們同步。
類Producer是生產(chǎn)者模型,其中的 run()方法中定義了生產(chǎn)者線程所做的操作,循環(huán)調(diào)用push()方法,將生產(chǎn)的20個(gè)字母送入堆棧中,每次執(zhí)行完push操作后,調(diào)用sleep()方法睡眠一段隨機(jī)時(shí)間,以給其他線程執(zhí)行的機(jī)會(huì)。類Consumer是消費(fèi)者模型,循環(huán)調(diào)用pop()方法,從堆棧中取出一個(gè)數(shù)據(jù),一共取20次,每次執(zhí)行完pop操作后,調(diào)用sleep()方法睡眠一段隨機(jī)時(shí)間,以給其他線程執(zhí)行的機(jī)會(huì)。
程序執(zhí)行結(jié)果
Produced:V
Consumed:V
Produced:E
Consumed:E
Produced:P
Produced:L
...
Consumed:L
Consumed:P
在上述的例子中,通過(guò)運(yùn)用wait()和notify()方法來(lái)實(shí)現(xiàn)線程的同步,在同步中還會(huì)用到notifyAll()方法,一般來(lái)說(shuō),每個(gè)共享對(duì)象的互斥鎖存在兩個(gè)隊(duì)列,一個(gè)是鎖等待隊(duì)列,另一個(gè)是鎖申請(qǐng)隊(duì)列,鎖申請(qǐng)隊(duì)列中的第一個(gè)線程可以對(duì)該共享對(duì)象進(jìn)行操作,而鎖等待隊(duì)列中的線程在某些情況下將移入到鎖申請(qǐng)隊(duì)列。下面比較一下wait()、notify()和notifyAll()方法:
(1) wait,nofity,notifyAll必須在已經(jīng)持有鎖的情況下執(zhí)行,所以它們只能出現(xiàn)在synchronized作用的范圍內(nèi),也就是出現(xiàn)在用 synchronized修飾的方法或類中。
(2) wait的作用:釋放已持有的鎖,進(jìn)入等待隊(duì)列. 來(lái)源:www.examda.com
(3) notify的作用:喚醒wait隊(duì)列中的第一個(gè)線程并把它移入鎖申請(qǐng)隊(duì)列.
(4) notifyAll的作用:喚醒wait隊(duì)列中的所有的線程并把它們移入鎖申請(qǐng)隊(duì)列.
注意:
1) suspend()和resume()
在JDK1.2中不再使用suspend()和resume(),其相應(yīng)功能由wait()和notify()來(lái)實(shí)現(xiàn)。
2) stop()
在JDK1.2中不再使用stop(),而是通過(guò)標(biāo)志位來(lái)使程序正常執(zhí)行完畢。