同步和通訊的目的是一樣的,實(shí)現(xiàn)進(jìn)程間數(shù)據(jù)共享,同步只是為了做到處理協(xié)同。
共享內(nèi)存在Win9X平臺(tái)上是有的,在NT內(nèi)核以后就沒(méi)有這一說(shuō)了,因?yàn)檫M(jìn)程地址空間不再有共用部分 Linux :通信就是說(shuō)進(jìn)程之間傳遞數(shù)據(jù)。常見(jiàn)的方法有 pipe(管道),F(xiàn)IFO(命名管道),socket(套接字),SysVIPC 的 shm(共享內(nèi)存)、msg queue(消息隊(duì)列),mmap(文件映射)。
以前還有 STREAM,不過(guò)現(xiàn)在比較少見(jiàn)了(好像)。 同步的意思是說(shuō),讓不同進(jìn)程能夠在同時(shí)到達(dá)一個(gè)已知的特定狀態(tài)之前等待另一方的執(zhí)行。
Linux 下常見(jiàn)的同步方法有SysVIPC 的 sem(信號(hào)量)、file locking / record locking(通過(guò) fcntl 設(shè)定的文件鎖、記錄鎖)、futex(基于共享內(nèi)存的快速用戶態(tài)互斥鎖)。針對(duì)線程(pthread)的還有 pthread_mutex 和 pthread_cond(條件變量)。
除了這些特定的同步對(duì)象之外,還有一些同步方法是與通信方法不可分離的,包括:對(duì) pipe/FIFO/socket 和 msg queue 的阻塞等待、對(duì)子進(jìn)程退出事件的等待(wait族)、對(duì)線程退出時(shí)間的等待(pthread_join) 另外還有一個(gè)不能不提的,就是信號(hào)。
進(jìn)程間通信機(jī)制 1 文件映射 文件映射(Memory-Mapped Files)能使進(jìn)程把文件內(nèi)容當(dāng)作進(jìn)程地址區(qū)間一塊內(nèi)存那樣來(lái)對(duì)待。
因此,進(jìn)程不必使用文件I/O操作,只需簡(jiǎn)單的指針操作就可讀取和修改文件的內(nèi)容。 Win32 API允許多個(gè)進(jìn)程訪問(wèn)同一文件映射對(duì)象,各個(gè)進(jìn)程在它自己的地址空間里接收內(nèi)存的指針。
通過(guò)使用這些指針,不同進(jìn)程就可以讀或修改文件的內(nèi)容,實(shí)現(xiàn)了對(duì)文件中數(shù)據(jù)的共享。 應(yīng)用程序有三種方法來(lái)使多個(gè)進(jìn)程共享一個(gè)文件映射對(duì)象。
(1)繼承:第一個(gè)進(jìn)程建立文件映射對(duì)象,它的子進(jìn)程繼承該對(duì)象的句柄。 (2)命名文件映射:第一個(gè)進(jìn)程在建立文件映射對(duì)象時(shí)可以給該對(duì)象指定一個(gè)名字(可與文件名不同)。
第二個(gè)進(jìn)程可通過(guò)這個(gè)名字打開(kāi)此文件映射對(duì)象。另外,第一個(gè)進(jìn)程也可以通過(guò)一些其它IPC機(jī)制(有名管道、郵件槽等)把名字傳給第二個(gè)進(jìn)程。
(3)句柄復(fù)制:第一個(gè)進(jìn)程建立文件映射對(duì)象,然后通過(guò)其它IPC機(jī)制(有名管道、郵件槽等)把對(duì)象句柄傳遞給第二個(gè)進(jìn)程。第二個(gè)進(jìn)程復(fù)制該句柄就取得對(duì)該文件映射對(duì)象的訪問(wèn)權(quán)限。
文件映射是在多個(gè)進(jìn)程間共享數(shù)據(jù)的非常有效方法,有較好的安全性。但文件映射只能用于本地機(jī)器的進(jìn)程之間,不。
進(jìn)程間通信機(jī)制 1 文件映射 文件映射(Memory-Mapped Files)能使進(jìn)程把文件內(nèi)容當(dāng)作進(jìn)程地址區(qū)間一塊內(nèi)存那樣來(lái)對(duì)待。因此,進(jìn)程不必使用文件I/O操作,只需簡(jiǎn)單的指針操作就可讀取和修改文件的內(nèi)容。
Win32 API允許多個(gè)進(jìn)程訪問(wèn)同一文件映射對(duì)象,各個(gè)進(jìn)程在它自己的地址空間里接收內(nèi)存的指針。通過(guò)使用這些指針,不同進(jìn)程就可以讀或修改文件的內(nèi)容,實(shí)現(xiàn)了對(duì)文件中數(shù)據(jù)的共享。
應(yīng)用程序有三種方法來(lái)使多個(gè)進(jìn)程共享一個(gè)文件映射對(duì)象。 (1)繼承:第一個(gè)進(jìn)程建立文件映射對(duì)象,它的子進(jìn)程繼承該對(duì)象的句柄。
(2)命名文件映射:第一個(gè)進(jìn)程在建立文件映射對(duì)象時(shí)可以給該對(duì)象指定一個(gè)名字(可與文件名不同)。第二個(gè)進(jìn)程可通過(guò)這個(gè)名字打開(kāi)此文件映射對(duì)象。
另外,第一個(gè)進(jìn)程也可以通過(guò)一些其它IPC機(jī)制(有名管道、郵件槽等)把名字傳給第二個(gè)進(jìn)程。 (3)句柄復(fù)制:第一個(gè)進(jìn)程建立文件映射對(duì)象,然后通過(guò)其它IPC機(jī)制(有名管道、郵件槽等)把對(duì)象句柄傳遞給第二個(gè)進(jìn)程。
第二個(gè)進(jìn)程復(fù)制該句柄就取得對(duì)該文件映射對(duì)象的訪問(wèn)權(quán)限。 文件映射是在多個(gè)進(jìn)程間共享數(shù)據(jù)的非常有效方法,有較好的安全性。
但文件映射只能用于本地機(jī)器的進(jìn)程之間,不能用于網(wǎng)絡(luò)中,而開(kāi)發(fā)者還必須控制進(jìn)程間的同步。 2 共享內(nèi)存 Win32 API中共享內(nèi)存(Shared Memory)實(shí)際就是文件映射的一種特殊情況。
進(jìn)程在創(chuàng)建文件映射對(duì)象時(shí)用0xFFFFFFFF來(lái)代替文件句柄(HANDLE),就表示了對(duì)應(yīng)的文件映射對(duì)象是從操作系統(tǒng)頁(yè)面文件訪問(wèn)內(nèi)存,其它進(jìn)程打開(kāi)該文件映射對(duì)象就可以訪問(wèn)該內(nèi)存塊。由于共享內(nèi)存是用文件映射實(shí)現(xiàn)的,所以它也有較好的安全性,也只能運(yùn)行于同一計(jì)算機(jī)上的進(jìn)程之間。
注意點(diǎn): 要控制同步,而且CString、list、arry、map等的collect class都不能安全的使用于共享內(nèi)存中 不要把擁有虛函數(shù)之C++類放到共享內(nèi)存中 不要把CObject派生類之MFC對(duì)象放到共享內(nèi)存中 不要使用"point within the shared memory"的指針 不要使用"point outside of the shared memory"的指針 使用"based"指針是安全的,但要小心使用 3 匿名管道 管道(Pipe)是一種具有兩個(gè)端點(diǎn)的通信通道:有一端句柄的進(jìn)程可以和有另一端句柄的進(jìn)程通信。管道可以是單向-一端是只讀的,另一端點(diǎn)是只寫(xiě)的;也可以是雙向的一管道的兩端點(diǎn)既可讀也可寫(xiě)。
匿名管道(Anonymous Pipe)是 在父進(jìn)程和子進(jìn)程之間,或同一父進(jìn)程的兩個(gè)子進(jìn)程之間傳輸數(shù)據(jù)的無(wú)名字的單向管道。通常由父進(jìn)程創(chuàng)建管道,然后由要通信的子進(jìn)程繼承通道的讀端點(diǎn)句柄或?qū)?端點(diǎn)句柄,然后實(shí)現(xiàn)通信。
父進(jìn)程還可以建立兩個(gè)或更多個(gè)繼承匿名管道讀和寫(xiě)句柄的子進(jìn)程。這些子進(jìn)程可以使用管道直接通信,不需要通過(guò)父進(jìn)程。
匿名管道是單機(jī)上實(shí)現(xiàn)子進(jìn)程標(biāo)準(zhǔn)I/O重定向的有效方法,它不能在網(wǎng)上使用,也不能用于兩個(gè)不相關(guān)的進(jìn)程之間。 4 命名管道 命名管道(Named Pipe)是服務(wù)器進(jìn)程和一個(gè)或多個(gè)客戶進(jìn)程之間通信的單向或雙向管道。
不同于匿名管道的是命名管道可以在不相關(guān)的進(jìn)程之間和不同計(jì)算機(jī)之間使用,服務(wù)器建立命名管道時(shí)給它指定一個(gè)名字,任何進(jìn)程都可以通過(guò)該名字打開(kāi)管道的另一端,根據(jù)給定的權(quán)限和服務(wù)器進(jìn)程通信。 命名管道提供了相對(duì)簡(jiǎn)單的編程接口,使通過(guò)網(wǎng)絡(luò)傳輸數(shù)據(jù)并不比同一計(jì)算機(jī)上兩進(jìn)程之間通信更困難,不過(guò)如果要同時(shí)和多個(gè)進(jìn)程通信它就力不從心了。
5 郵件槽 郵件槽(Mailslots)提 供進(jìn)程間單向通信能力,任何進(jìn)程都能建立郵件槽成為郵件槽服務(wù)器。其它進(jìn)程,稱為郵件槽客戶,可以通過(guò)郵件槽的名字給郵件槽服務(wù)器進(jìn)程發(fā)送消息。
進(jìn)來(lái)的消 息一直放在郵件槽中,直到服務(wù)器進(jìn)程讀取它為止。一個(gè)進(jìn)程既可以是郵件槽服務(wù)器也可以是郵件槽客戶,因此可建立多個(gè)郵件槽實(shí)現(xiàn)進(jìn)程間的雙向通信。
通過(guò)郵件槽可以給本地計(jì)算機(jī)上的郵件槽、其它計(jì)算機(jī)上的郵件槽或指定網(wǎng)絡(luò)區(qū)域中所。
現(xiàn)在最常用的進(jìn)程間通信的方式有:信號(hào),信號(hào)量,消息隊(duì)列,共享內(nèi)存。
所謂進(jìn)程通信,就是不同進(jìn)程之間進(jìn)行一些"接觸",這種接觸有簡(jiǎn)單,也有復(fù)雜。機(jī)制不同,復(fù)雜度也不一樣。通信是一個(gè)廣義上的意義,不僅僅指?jìng)鬟f一些massege。
他們的使用方法是基本相同的,所以只要掌握了一種的使用方法,然后記住其他的使用方法就可以了。
1. 信號(hào)
在我學(xué)習(xí)的內(nèi)容中,主要接觸了信號(hào)來(lái)實(shí)現(xiàn)同步的機(jī)制,據(jù)說(shuō)信號(hào)也可以用來(lái)做其它的事情,但是我還不知道做什么。
信號(hào)和信號(hào)量是不同的,他們雖然都可用來(lái)實(shí)現(xiàn)同步和互斥,但前者是使用信號(hào)處理器來(lái)進(jìn)行的,后者是使用P,V操作來(lái)實(shí)現(xiàn)的。
使用信號(hào)要先知道有哪些信號(hào),在Linux下有31個(gè)需要記住的通用信號(hào),據(jù)說(shuō)也是systemV中最常用的那些。這里略。
1. 1信號(hào)相關(guān)函數(shù):
#include
int sigaction(int signo, const struct sigaction *act, struct sigaction
*oact);
該函數(shù)用來(lái)為進(jìn)程安裝信號(hào)處理器,struct sigaction數(shù)據(jù)是用來(lái)保存信號(hào)處理器的相關(guān)信息。
#include
int sigemptyset(sigset_t *set);
將信號(hào)集合清空。
int sigfillset(sigset_t *set);
將信號(hào)集合設(shè)置成包含所有的信號(hào)。在對(duì)信號(hào)進(jìn)行操作以前一定要對(duì)信號(hào)集進(jìn)行初始化。
int sigaddset(sigset_t *set, int signo);
向信號(hào)集中加入signo對(duì)應(yīng)的新信號(hào)。
int sigdelset(sigset_t *set, int signo);
從信號(hào)集中刪除signo對(duì)應(yīng)的一個(gè)信號(hào)。
int sigismember(const sigset_t *set, int signo);
判斷某個(gè)信號(hào)是否在信號(hào)集中。返回1則在,0則不在。
#include
int sigprocmask(int how,const sigset_t *set, sigset_t *oset);用來(lái)設(shè)置進(jìn)程的信號(hào)屏蔽碼。信號(hào)屏蔽碼可以用來(lái)在某段時(shí)間內(nèi)阻塞一些信號(hào)集中的信號(hào),如果信號(hào)不在信號(hào)集中,就不必討論它,因?yàn)榭隙ú豁憫?yīng),是否能生成也不肯定,我沒(méi)有做過(guò)試驗(yàn)。
1.2我所理解的使用信號(hào)機(jī)制的方法:
使用信號(hào),主要做的事情就是信號(hào)處理器的工作,這里面是你想做的事情。就像中斷處理函數(shù)一樣。
在使用信號(hào)以前,首先要初始化信號(hào)集,只有在信號(hào)集里面的信號(hào)才會(huì)被考慮。
有兩種方法可以初始化信號(hào)集,一種是設(shè)置空信號(hào)集,一種是將所有的信號(hào)都加到信號(hào)集中。如果你自己想要的信號(hào)集不是這兩種,可以在初始化了以后通過(guò)添加和刪除信號(hào)進(jìn)行定制。
如果在進(jìn)程執(zhí)行的一段時(shí)間內(nèi)不想對(duì)某些信號(hào)進(jìn)行響應(yīng),則可以使用sigprocmask對(duì)當(dāng)前的信號(hào)集中的一些信號(hào)進(jìn)行阻塞,稍后再執(zhí)行。
用于進(jìn)程間通訊(IPC)的四種不同技術(shù):
1. 消息傳遞(管道,F(xiàn)IFO,posix和system v消息隊(duì)列)
2. 同步(互斥鎖,條件變量,讀寫(xiě)鎖,文件和記錄鎖,Posix和System V信號(hào)燈)
3. 共享內(nèi)存區(qū)(匿名共享內(nèi)存區(qū),有名Posix共享內(nèi)存區(qū),有名System V共享內(nèi)存區(qū))
4. 過(guò)程調(diào)用(Solaris門,Sun RPC)
消息隊(duì)列和過(guò)程調(diào)用往往單獨(dú)使用,也就是說(shuō)它們通常提供了自己的同步機(jī)制.相反,共享內(nèi)存區(qū)通常需要由應(yīng)用程序提供的某種同步形式才能正常工作.解決某個(gè)特定問(wèn)題應(yīng)使用哪種IPC不存在簡(jiǎn)單的判定,應(yīng)該逐漸熟悉各種IPC形式提供的機(jī)制,然后根據(jù)特定應(yīng)用的要求比較它們的特性.
必須考慮的四個(gè)前提:
1. 聯(lián)網(wǎng)的還是非聯(lián)網(wǎng)的.IPC適用于單臺(tái)主機(jī)上的進(jìn)程或線程間的.如果應(yīng)用程序有可能分布到多臺(tái)主機(jī)上,那就要考慮使用套接字代替IPC,從而簡(jiǎn)化以后向聯(lián)網(wǎng)的應(yīng)用程序轉(zhuǎn)移的工作.
2. 可移植性.
3. 性能,在具體的開(kāi)發(fā)環(huán)境下運(yùn)行測(cè)試程序,比較幾種IPC的性能差異.
4. 實(shí)時(shí)調(diào)度.如果需要這一特性,而且所用的系統(tǒng)也支持posix實(shí)時(shí)調(diào)度選項(xiàng),那就考慮使用Posix的消息傳遞和同步函數(shù).
各種IPC之間的一些主要差異:
1. 管道和FIFO是字節(jié)流,沒(méi)有消息邊界.Posix消息和System V消息則有從發(fā)送者向接受者維護(hù)的記錄邊界(eg:TCP是沒(méi)有記錄邊界的字節(jié)流,UDP則提供具有記錄邊界的消息).
2. 當(dāng)有一個(gè)消息放置到一個(gè)空隊(duì)列中時(shí),Posix消息隊(duì)列可向一個(gè)進(jìn)程發(fā)送一個(gè)信號(hào),或者啟動(dòng)一個(gè)新的線程.System V則不提供類似的通知形式.
3. 管道和FIFO的數(shù)據(jù)字節(jié)是先進(jìn)先出的.Posix消息和System V消息具有由發(fā)送者賦予的優(yōu)先級(jí).從一個(gè)Posix消息隊(duì)列讀出時(shí),首先返回的總是優(yōu)先級(jí)最高的消息.從一個(gè)System V消息隊(duì)列讀出時(shí),讀出者可以要求想要的任意優(yōu)先級(jí)的消息.
4. 在眾多的消息傳遞技術(shù)—管道,F(xiàn)IFO,Posix消息隊(duì)列和System V消息隊(duì)列—中,可從一個(gè)信號(hào)處理程序中調(diào)用的函數(shù)只有read和write(適用于管道和FIFO).
比較不同形式的消息傳遞時(shí),我們感興趣的有兩種測(cè)量尺度:
1. 帶寬(bandwidth):數(shù)據(jù)通過(guò)IPC通道轉(zhuǎn)移的速度.為測(cè)量該值,我們從一個(gè)進(jìn)程向另一個(gè)進(jìn)程發(fā)送大量數(shù)據(jù)(幾百萬(wàn)字節(jié)).我們還給不同大小的I/O操作(例如管道和FIFO的write和read操作)測(cè)量該值,期待發(fā)現(xiàn)帶寬隨每個(gè)I/O操作的數(shù)據(jù)量的增長(zhǎng)而增長(zhǎng)的規(guī)律.
2. 延遲(latency):一個(gè)小的IPC消息從一個(gè)進(jìn)程到令一個(gè)進(jìn)程再返回來(lái)所花的時(shí)間.我們測(cè)量的是只有一個(gè)1個(gè)字節(jié)的消息從一個(gè)進(jìn)程到令一個(gè)進(jìn)程再回來(lái)的時(shí)間(往返時(shí)間)
在現(xiàn)實(shí)世界中,帶寬告訴我們大塊數(shù)據(jù)通過(guò)一個(gè)IPC通道發(fā)送出去需花多長(zhǎng)時(shí)間,然而IPC也用于傳遞小的控制信息,系統(tǒng)處理這些小消息所需的時(shí)間就由延遲提供.這兩個(gè)數(shù)都很重要.
什么是系統(tǒng)進(jìn)程
進(jìn)程是指在系統(tǒng)中正在運(yùn)行的一個(gè)應(yīng)用程序;線程是系統(tǒng)分配處理器時(shí)間資源的基本單元,或者說(shuō)進(jìn)程之內(nèi)獨(dú)立執(zhí)行的一個(gè)單元。對(duì)于操作系統(tǒng)而言,其調(diào)度單元是線程。一個(gè)進(jìn)程至少包括一個(gè)線程,通常將該線程稱為主線程。一個(gè)進(jìn)程從主線程的執(zhí)行開(kāi)始進(jìn)而創(chuàng)建一個(gè)或多個(gè)附加線程,就是所謂基于多線程的多任務(wù)。
那進(jìn)程與線程的區(qū)別到底是什么?進(jìn)程是執(zhí)行程序的實(shí)例。例如,當(dāng)你運(yùn)行記事本程序(Nodepad)時(shí),你就創(chuàng)建了一個(gè)用來(lái)容納組成 Notepad.exe的代碼及其所需調(diào)用動(dòng)態(tài)鏈接庫(kù)的進(jìn)程。每個(gè)進(jìn)程均運(yùn)行在其專用且受保護(hù)的地址空間內(nèi)。因此,如果你同時(shí)運(yùn)行記事本的兩個(gè)拷貝,該程序正在使用的數(shù)據(jù)在各自實(shí)例中是彼此獨(dú)立的。在記事本的一個(gè)拷貝中將無(wú)法看到該程序的第二個(gè)實(shí)例打開(kāi)的數(shù)據(jù)。
以沙箱為例進(jìn)行闡述。一個(gè)進(jìn)程就好比一個(gè)沙箱。線程就如同沙箱中的孩子們。孩子們?cè)谏诚渥又信軄?lái)跑去,并且可能將沙子攘到別的孩子眼中,他們會(huì)互相踢打或撕咬。但是,這些沙箱略有不同之處就在于每個(gè)沙箱完全由墻壁和頂棚封閉起來(lái),無(wú)論箱中的孩子如何狠命地攘沙,他們也不會(huì)影響到其它沙箱中的其他孩子。因此,每個(gè)進(jìn)程就象一個(gè)被保護(hù)起來(lái)的沙箱。未經(jīng)許可,無(wú)人可以進(jìn)出。
實(shí)際上線程運(yùn)行而進(jìn)程不運(yùn)行。兩個(gè)進(jìn)程彼此獲得專用數(shù)據(jù)或內(nèi)存的唯一途徑就是通過(guò)協(xié)議來(lái)共享內(nèi)存塊。這是一種協(xié)作策略。下面讓我們分析一下任務(wù)管理器里的進(jìn)程選項(xiàng)卡。
這里的進(jìn)程是指一系列進(jìn)程,這些進(jìn)程是由它們所運(yùn)行的可執(zhí)行程序?qū)嵗齺?lái)識(shí)別的,這就是進(jìn)程選項(xiàng)卡中的第一列給出了映射名稱的原因。請(qǐng)注意,這里并沒(méi)有進(jìn)程名稱列。進(jìn)程并不擁有獨(dú)立于其所歸屬實(shí)例的映射名稱。換言之,如果你運(yùn)行5個(gè)記事本拷貝,你將會(huì)看到5個(gè)稱為Notepad.exe的進(jìn)程。它們是如何彼此區(qū)別的呢?其中一種方式是通過(guò)它們的進(jìn)程ID,因?yàn)槊總€(gè)進(jìn)程都擁有其獨(dú)一無(wú)二的編碼。該進(jìn)程ID由Windows NT或Windows 2000生成,并可以循環(huán)使用。因此,進(jìn)程ID將不會(huì)越編越大,它們能夠得到循環(huán)利用。第三列是被進(jìn)程中的線程所占用的CPU時(shí)間百分比。它不是CPU的編號(hào),而是被進(jìn)程占用的CPU時(shí)間百分比。此時(shí)我的系統(tǒng)基本上是空閑的。盡管系統(tǒng)看上去每一秒左右都只使用一小部分CPU時(shí)間,但該系統(tǒng)空閑進(jìn)程仍舊耗用了大約99%的CPU時(shí)間。
第四列,CPU時(shí)間,是CPU被進(jìn)程中的線程累計(jì)占用的小時(shí)、分鐘及秒數(shù)。請(qǐng)注意,我對(duì)進(jìn)程中的線程使用占用一詞。這并不一定意味著那就是進(jìn)程已耗用的CPU時(shí)間總和,因?yàn)椋缥覀円粫?huì)兒將看到的,NT計(jì)時(shí)的方式是,當(dāng)特定的時(shí)鐘間隔激發(fā)時(shí),無(wú)論誰(shuí)恰巧處于當(dāng)前的線程中,它都將計(jì)算到CPU周期之內(nèi)。通常情況下,在大多數(shù)NT系統(tǒng)中,時(shí)鐘以10毫秒的間隔運(yùn)行。每10毫秒NT的心臟就跳動(dòng)一下。有一些驅(qū)動(dòng)程序代碼片段運(yùn)行并顯示誰(shuí)是當(dāng)前的線程。讓我們將CPU時(shí)間的最后10毫秒記在它的帳上。因此,如果一個(gè)線程開(kāi)始運(yùn)行,并在持續(xù)運(yùn)行8毫秒后完成,接著,第二個(gè)線程開(kāi)始運(yùn)行并持續(xù)了2毫秒,這時(shí),時(shí)鐘激發(fā),請(qǐng)猜一猜這整整10毫秒的時(shí)鐘周期到底記在了哪個(gè)線程的帳上?答案是第二個(gè)線程。因此,NT中存在一些固有的不準(zhǔn)確性,而NT恰是以這種方式進(jìn)行計(jì)時(shí),實(shí)際情況也如是,大多數(shù)32位操作系統(tǒng)中都存在一個(gè)基于間隔的計(jì)時(shí)機(jī)制。請(qǐng)記住這一點(diǎn),因?yàn)椋袝r(shí)當(dāng)你觀察線程所耗用的CPU總和時(shí),會(huì)出現(xiàn)盡管該線程或許看上去已運(yùn)行過(guò)數(shù)十萬(wàn)次,但其CPU時(shí)間占用量卻可能是零或非常短暫的現(xiàn)象,那么,上述解釋便是原因所在。上述也就是我們?cè)谌蝿?wù)管理器的進(jìn)程選項(xiàng)卡中所能看到的基本信息列。
1。同步代碼塊:
synchronized(同一個(gè)數(shù)據(jù)){} 同一個(gè)數(shù)據(jù):就是N條線程同時(shí)訪問(wèn)一個(gè)數(shù)據(jù)。
2。
同步方法:
public synchronized 數(shù)據(jù)返回類型 方法名(){}
就
是使用 synchronized 來(lái)修飾某個(gè)方法,則該方法稱為同步方法。對(duì)于同步方法而言,無(wú)需顯示指定同步監(jiān)視器,同步方法的同步監(jiān)視器是
this
也就是該對(duì)象的本身(這里指的對(duì)象本身有點(diǎn)含糊,其實(shí)就是調(diào)用該同步方法的對(duì)象)通過(guò)使用同步方法,可非常方便的將某類變成線程安全的類,具有如下特征:
1,該類的對(duì)象可以被多個(gè)線程安全的訪問(wèn)。
2,每個(gè)線程調(diào)用該對(duì)象的任意方法之后,都將得到正確的結(jié)果。
3,每個(gè)線程調(diào)用該對(duì)象的任意方法之后,該對(duì)象狀態(tài)依然保持合理狀態(tài)。
注:synchronized關(guān)鍵字可以修飾方法,也可以修飾代碼塊,但不能修飾構(gòu)造器,屬性等。
實(shí)現(xiàn)同步機(jī)制注意以下幾點(diǎn): 安全性高,性能低,在多線程用。性能高,安全性低,在單線程用。
1,不要對(duì)線程安全類的所有方法都進(jìn)行同步,只對(duì)那些會(huì)改變共享資源方法的進(jìn)行同步。
2,如果可變類有兩種運(yùn)行環(huán)境,當(dāng)線程環(huán)境和多線程環(huán)境則應(yīng)該為該可變類提供兩種版本:線程安全版本和線程不安全版本(沒(méi)有同步方法和同步塊)。在單線程中環(huán)境中,使用線程不安全版本以保證性能,在多線程中使用線程安全版本.
線程通訊:
為什么要使用線程通訊?
當(dāng)
使用synchronized
來(lái)修飾某個(gè)共享資源時(shí)(分同步代碼塊和同步方法兩種情況),當(dāng)某個(gè)線程獲得共享資源的鎖后就可以執(zhí)行相應(yīng)的代碼段,直到該線程運(yùn)行完該代碼段后才釋放對(duì)該
共享資源的鎖,讓其他線程有機(jī)會(huì)執(zhí)行對(duì)該共享資源的修改。當(dāng)某個(gè)線程占有某個(gè)共享資源的鎖時(shí),如果另外一個(gè)線程也想獲得這把鎖運(yùn)行就需要使用wait()
和notify()/notifyAll()方法來(lái)進(jìn)行線程通訊了。
Java.lang.object 里的三個(gè)方法wait() notify() notifyAll()
wait方法導(dǎo)致當(dāng)前線程等待,直到其他線程調(diào)用同步監(jiān)視器的notify方法或notifyAll方法來(lái)喚醒該線程。
wait(mills)方法
都是等待指定時(shí)間后自動(dòng)蘇醒,調(diào)用wait方法的當(dāng)前線程會(huì)釋放該同步監(jiān)視器的鎖定,可以不用notify或notifyAll方法把它喚醒。
notify()
喚醒在同步監(jiān)視器上等待的單個(gè)線程,如果所有線程都在同步監(jiān)視器上等待,則會(huì)選擇喚醒其中一個(gè)線程,選擇是任意性的,只有當(dāng)前線程放棄對(duì)該同步監(jiān)視器的鎖定后,也就是使用wait方法后,才可以執(zhí)行被喚醒的線程。
notifyAll()方法
喚醒在同步監(jiān)視器上等待的所有的線程。只用當(dāng)前線程放棄對(duì)該同步監(jiān)視器的鎖定后,才可以執(zhí)行被喚醒的線程
lz你好,
在操作系統(tǒng)中,有很多術(shù)語(yǔ)都是想通的,都是相似的,相近的。比如同步、異步、并行、并發(fā)、互斥等等。對(duì)這類詞語(yǔ),如果沒(méi)有同時(shí)出現(xiàn),我們對(duì)它們最好的處理就是不去比較它們,因?yàn)楹芏喽紱](méi)有可比性。
首先:互斥和同步如果是同時(shí)出現(xiàn)的話,那就是相反的,值得比較的兩個(gè)術(shù)語(yǔ)。
【互斥】:就是說(shuō)兩個(gè)進(jìn)程只能在某一時(shí)刻執(zhí)行一個(gè),這種結(jié)果可能是因?yàn)楣餐瑺?zhēng)奪資源而產(chǎn)生的。舉個(gè)例子:假設(shè)把火車上的公共廁所看成一種臨界資源,而兩個(gè)乘客是兩個(gè)進(jìn)程,我們就可以認(rèn)為同時(shí)需要使用公共廁所的乘客是互斥的
【同步】:就是進(jìn)程之間可以同時(shí)運(yùn)行的,之間并不存在“利益沖突”,不競(jìng)爭(zhēng)資源。大有“你走你的陽(yáng)關(guān)道,我過(guò)我的獨(dú)木橋”之意,兩個(gè)進(jìn)程互不干涉,互不影響。
說(shuō)的很直白了,希望可以幫你o(∩_∩)o
聲明:本網(wǎng)站尊重并保護(hù)知識(shí)產(chǎn)權(quán),根據(jù)《信息網(wǎng)絡(luò)傳播權(quán)保護(hù)條例》,如果我們轉(zhuǎn)載的作品侵犯了您的權(quán)利,請(qǐng)?jiān)谝粋€(gè)月內(nèi)通知我們,我們會(huì)及時(shí)刪除。
蜀ICP備2020033479號(hào)-4 Copyright ? 2016 學(xué)習(xí)鳥(niǎo). 頁(yè)面生成時(shí)間:2.956秒