新聞中心
Linux操作系統(tǒng)中,信號量是一種用于進(jìn)程間同步和互斥的重要機制。它可以保證多個進(jìn)程在同一個資源上互斥的訪問,從而避免了數(shù)據(jù)競爭和死鎖的問題。而信號量的管理和同步則是由Seminit系統(tǒng)調(diào)用來實現(xiàn)的。

10多年的阿拉山口網(wǎng)站建設(shè)經(jīng)驗,針對設(shè)計、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時及時工作處理。營銷型網(wǎng)站建設(shè)的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整阿拉山口建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計,從而大程度地提升瀏覽體驗。成都創(chuàng)新互聯(lián)公司從事“阿拉山口網(wǎng)站設(shè)計”,“阿拉山口網(wǎng)站推廣”以來,每個客戶項目都認(rèn)真落實執(zhí)行。
Seminit的介紹
Seminit系統(tǒng)調(diào)用是Linux內(nèi)核中用于創(chuàng)建和初始化信號量的系統(tǒng)調(diào)用。它的定義和作用與其他類型的同步原語如mutexes、condvars和rwlocks等非常類似,但是它更為靈活,可以用于實現(xiàn)更為復(fù)雜的同步操作。
Seminit系統(tǒng)調(diào)用的定義如下:
“`c
#include
int seminit (key_t key, int nsems, int sem);
“`
其中,key是一個32位的鍵值,用于在系統(tǒng)中唯一標(biāo)識一個信號量集;nsems指定需要創(chuàng)建的信號量集中的信號量數(shù)量,sem指定創(chuàng)建時的額外選項,比如是否允許多個進(jìn)程共享同一個信號量集。
Seminit系統(tǒng)調(diào)用的主要作用是創(chuàng)建一個新的信號量集,或者打開已經(jīng)存在的信號量集。在創(chuàng)建信號量集時,Seminit將分配一個新的信號量數(shù)組,并對它進(jìn)行初始化。在打開已經(jīng)存在的信號量集時,Seminit將直接返回一個指向該信號量集的標(biāo)識符,不需要做太多的初始化工作。
創(chuàng)建信號量
創(chuàng)建信號量集的過程非常簡單,只需要調(diào)用Seminit系統(tǒng)調(diào)用,并傳遞需要創(chuàng)建的信號量數(shù)量即可。如下面的示例所示:
“`c
key_t key = ftok(“/tmp/semfile”, ‘S’);
int nsems = 5;
int semid = seminit(key, nsems, IPC_CREAT | IPC_EXCL | 0666);
if (semid == -1) {
perror(“semget”);
exit(EXIT_FLURE);
}
for (int i = 0; i
struct sembuf op = { .sem_num = i, .sem_op = 1, .sem_ = 0 };
semop(semid, &op, 1);
}
“`
在這個示例中,我們首先使用ftok函數(shù)生成一個鍵值,然后調(diào)用Seminit系統(tǒng)調(diào)用創(chuàng)建一個新的包含nsems個信號量的信號量集。如果創(chuàng)建成功,Seminit將返回一個標(biāo)識符semid,我們可以用于后續(xù)的信號量操作。
初始化信號量
創(chuàng)建好信號量集之后,我們還需要對信號量進(jìn)行初始化。這通常是通過調(diào)用Semctl系統(tǒng)調(diào)用實現(xiàn)的,它可以修改或查詢一個指定的信號量集中的某個或所有信號量。
下面是一個初始化信號量的示例代碼:
“`c
key_t key = ftok(“/tmp/semfile”, ‘S’);
int nsems = 5;
int semid = seminit(key, nsems, IPC_CREAT | IPC_EXCL | 0666);
if (semid == -1) {
perror(“semget”);
exit(EXIT_FLURE);
}
union semun arg;
arg.val = 0;
for (int i = 0; i
if (semctl(semid, i, SETVAL, arg) == -1) {
perror(“semctl”);
exit(EXIT_FLURE);
}
}
“`
在這個示例中,我們首先使用Seminit系統(tǒng)調(diào)用創(chuàng)建一個包含nsems個信號量的新信號量集。之后,我們定義了一個semun聯(lián)合體,并賦值為0,用于告訴Semctl系統(tǒng)調(diào)用我們希望將所有信號量的值都設(shè)定為0。我們通過循環(huán)調(diào)用Semctl系統(tǒng)調(diào)用來初始化所有信號量的值。
操作信號量
創(chuàng)建和初始化信號量之后,我們就可以開始使用它來實現(xiàn)同步互斥操作了。信號量的操作主要是通過Semop系統(tǒng)調(diào)用來實現(xiàn)的,它可以對指定的信號量執(zhí)行加鎖、解鎖等操作。
下面是一個操作信號量的示例代碼:
“`c
key_t key = ftok(“/tmp/semfile”, ‘S’);
int nsems = 5;
int semid = seminit(key, nsems, 0);
if (semid == -1) {
perror(“semget”);
exit(EXIT_FLURE);
}
struct sembuf op[] = {
{ .sem_num = 0, .sem_op = -1, .sem_ = SEM_UNDO },
{ .sem_num = 1, .sem_op = 1, .sem_ = SEM_UNDO }
};
if (semop(semid, op, 2) == -1) {
perror(“semop”);
exit(EXIT_FLURE);
}
“`
在這個示例中,我們使用Seminit系統(tǒng)調(diào)用打開已經(jīng)存在的信號量集,并使用結(jié)構(gòu)體數(shù)組指定了需要加鎖(之一個操作)和解鎖(第二個操作)的信號量。如果操作成功,Semop將返回0,否則將返回-1并設(shè)置errno來指示錯誤的原因。
相關(guān)問題拓展閱讀:
- linux 信號燈中線程切換問題
- 如何對讀寫鎖進(jìn)行處理
linux 信號燈中線程切換問題
(1)Posix標(biāo)準(zhǔn)中有有名信號燈和無名信號燈之分,對于有名信號燈,可以用sem_open來創(chuàng)建,其prototype是:
sem_t *sem_open(const char *name, int oflag);//打開已有的信號燈
sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned value);//一般是創(chuàng)建信號燈。
期中name是信號燈的名字, oflag是0, O_CREAT 或者 O_CREAT | O_EXCL, 如果指定O_CREAT, 那么mode和value對應(yīng)創(chuàng)建該信號的模式和初始值。 如果指定了O_EXCL, 而且該信號燈已經(jīng)在系統(tǒng)中存在,那調(diào)用會出錯返回SEM_FAILED常量。 對于Linux內(nèi)核來說,有名信號燈是很晚才加入內(nèi)核中的,創(chuàng)建或是打開有名信號時候,應(yīng)該指定”/semname“名字,對應(yīng)的信號燈創(chuàng)建在/dev/shm目錄下,名字是/dev/shm/sem.semname. W, 用gcc/g++編譯實用信號燈功能的程序時候,應(yīng)該引用librt庫,(e.g., g++ -lrt sem.cpp). 關(guān)閉已打開的信號燈,用sem_close(sem_t *sem). 關(guān)閉信號燈并不意味著系統(tǒng)會刪除它,要刪除一個信號燈,需要調(diào)用sem_unlink(sem_t *sem)。 有名信號燈一般是為了進(jìn)程之間同步實用的。 無名信號喚清燈,一般是為一個進(jìn)程內(nèi)的不同線程之間同步使用的。 創(chuàng)建無名信號燈的方法如下:
sem_t sem;
sem_init(&sem, int shared, unsigned int value);//初始化信號燈。
……
sem_destroy(&sem);//清除信號燈。
(2)信號燈的使用和狀態(tài)。
信號燈一般用來描述不同線程所共享的公共資源的數(shù)量,每一個信號燈都有一個叫做信號量的非負(fù)整數(shù)與之相連;信號量一般代表公共資源的數(shù)目,比如空閑列表中的緩沖區(qū)數(shù)目,視頻中讀入幀的數(shù)目,等等。對于一個線程可以用sem_wait, sem_post函數(shù)來改如缺變一個信號燈的信號量。
sem_wait(sem_t &sem);
sem_wait的語義如下:
{
while(信號量==0)
等待; //此處線程被掛起,等待其他線程調(diào)用sem_post喚醒之。
信號量減1;
}
注意:測試信號量是否為零,和減一的操作是原子的,也就是說期間不會發(fā)生線程切換。
與sem_wait對應(yīng)的調(diào)用是sem_post,語義如下:
{
信號量加1;
喚醒等待該信號量的線程;//調(diào)用sem_wait并等待的線程。
}
該操作也是原子的。
信號燈的狀態(tài)可以用sem_getvalue來查看。一般來說sem_wait和sem_post的調(diào)用不必在同一個線程內(nèi)成對出現(xiàn)(象mutex那樣,lock/unlock要配對出現(xiàn))。 一般的情形是這樣的,一個線程等待資源可用,調(diào)用sem_wait, 另外一個線程生成資源,然后調(diào)用sem_post,喚醒等待該資源的線程。因為信號燈和橡前所描述的是線程間公共資源,使用的時候一般和mutex一起使用,mutex保證訪問公共資源的線程排他性,信號燈表示資源的可用性。
如何對讀寫鎖進(jìn)行處理
信號量強調(diào)的是線程(或進(jìn)程)間的同步:“信號量用在多線程多任務(wù)同步的,一個線程完成了某一個動作就通過信號量告訴別的線程,別的線程再進(jìn)行某些動作(大家都 在sem_wait的時候,就枯虧御阻塞在那里)。當(dāng)信號量為單值信號量是,也可以完成一個資源的互斥訪問。
有名信號量:可以用于不同進(jìn)程間或多線程間的互斥與同步
創(chuàng)建打開空信有名信號量
sem_t *sem_open(const char *name, int oflag);
sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);
成功返回信號量指針;失敗返回SEM_FAILED,設(shè)置errnoname是文件路徑名,但不能寫成/tmp/a.sem這樣的形式,因為在linux下,sem都是在/dev/shm目錄下,可寫成”/mysem”或”mysem”,創(chuàng)建出來的文件都 是”/dev/shm/sem.mysem”,mode設(shè)置為0666,value設(shè)置為信號量的初始值.所需信號燈等已存在條件下指定O_CREAT|O_EXCL卻是個錯誤。
關(guān)閉信號量,進(jìn)程終止時,會自動調(diào)用它
int sem_close(sem_t *sem);
成功返回0;失敗返回-1,設(shè)置errno
刪除信號量,立即刪除信號量名字,當(dāng)其他進(jìn)程都關(guān)閉它時,銷毀它
int sem_unlink(const char *name);
等待信號量,測試信號量的值,如果其值小于或等于0,那么就等待(阻塞);一旦其值變?yōu)榇笥?就將它減1,并返回
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
成功返回0;失敗返回-1,設(shè)置errno
當(dāng)信號量的值為0時,sem_trywait立即返回,設(shè)置errno為EAGAIN。如果被某個信號中斷,sem_wait會過早地返回,設(shè)置errno為EINTR
發(fā)出信號量,給它的值加1,然后喚醒正在等待該信號量的進(jìn)程或線程
int sem_post(sem_t *sem);
成功返回0;失敗返回-1,不會改變它的值,設(shè)置errno,該函數(shù)是異步信號安全的,可以在信號處理程序里調(diào)用它無名信號量,用于進(jìn)程體內(nèi)各線程間的互斥和同步,使用如下API(無名信號量,基于內(nèi)存的信號量)
(1)、sem_init
功能:用于創(chuàng)建一個信號量,并初始化信號量的值。
頭文件:
函數(shù)原型: int sem_init (sem_t* sem, int pshared, unsigned int value);
函數(shù)傳入值: sem:信號量。pshared:決定信號量能否在幾個進(jìn)程間共享。由于目前LINUX還沒有實現(xiàn)進(jìn)程間共享信息量,所以這個值只能取0。
(2)其他函數(shù)。
int sem_wait (sem_t* sem);
int sem_trywait (sem_t* sem);
int sem_post (sem_t* sem);
int sem_getvalue (sem_t* sem);
int sem_destroy (sem_t* sem);
功能:sem_wait和sem_trywait相當(dāng)于P操作,它們都能將信號量的值減一,兩者的區(qū)別在于若信號量的值小于零時,sem_wait將會阻塞進(jìn)程,而sem_trywait則會立即返回。sem_post相當(dāng)于V操作,它將信號量的值加一,同時發(fā)出喚醒的信號給等待的進(jìn)程(或線程)。
sem_getvalue 得到信號量的值。
sem_destroy 摧毀信號量。
如果某個基于內(nèi)存的信號燈是在不同進(jìn)程間同步的,該信號燈必須存放在共享內(nèi)存區(qū)中,這要只要該共享內(nèi)存區(qū)存在,該信號燈就存在。
互斥鎖(又名互斥量)強調(diào)的是資源的訪問互斥:互斥鎖是用在多線程多任務(wù)互斥的,一個線程占用了某一個資源,那么別的線程就無法訪問,直到這個線程unlock,其他的線程才開始可以利用這個資源。比如對全局變量的訪問,有時要加鎖,操作完了,在解鎖。有的時候鎖和信號量會同時使用的”
也就是說,信號量不一定是鎖定某一個資源,而是流程上的概念,比如:有A,B兩個線程,B線程要等A線程完成某一任務(wù)以后再進(jìn)行自己下面的步驟,這個任務(wù)并不一定是鎖定某一資源,還可以是進(jìn)行一些計算或者數(shù)據(jù)處理之類。而線程互斥量則是“沒巖鎖住某一資源”的概念,在鎖定期間內(nèi),其他線程無法對被保護(hù)的數(shù)據(jù)進(jìn)行操作。在有些情況下兩者可以互換。
在linux下, 線程的互斥量數(shù)據(jù)類型是pthread_mutex_t. 在使用前, 要對它進(jìn)行初始化:
對于靜態(tài)分配的互斥量, 可以把它設(shè)置為PTHREAD_MUTEX_INITIALIZER, 或者調(diào)用pthread_mutex_init.
對于動態(tài)分配的互斥量, 在申請內(nèi)存(malloc)之后, 通過pthread_mutex_init進(jìn)行初始化, 并且在釋放內(nèi)存(free)前需要調(diào)用pthread_mutex_destroy.
原型:
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restric attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
頭文件:
返回值: 成功則返回0, 出錯則返回錯誤編號.
說明: 如果使用默認(rèn)的屬性初始化互斥量, 只需把attr設(shè)為NULL. 其他值在以后講解.
首先說一下加鎖函數(shù):
頭文件:
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
返回值: 成功則返回0, 出錯則返回錯誤編號.
說 明: 具體說一下trylock函數(shù), 這個函數(shù)是非阻塞調(diào)用模式, 也就是說, 如果互斥量沒被鎖住, trylock函數(shù)將把互斥量加鎖, 并獲得對共享資源的訪問權(quán)限; 如果互斥量 被鎖住了, trylock函數(shù)將不會阻塞等待而直接返回EBUSY, 表示共享資源處于忙狀態(tài).
再說一下解所函數(shù):
頭文件:
原型: int pthread_mutex_unlock(pthread_mutex_t *mutex);
返回值: 成功則返回0, 出錯則返回錯誤編號.
條件變量常與互斥鎖同時使用,達(dá)到線程同步的目的:條件變量通過允許線程阻塞和等待另一個線程發(fā)送信號的方法彌補了互斥鎖的不足。在發(fā) 送信號時,如果沒有線程 等待在該條件變量上,那么信號將丟失;而信號量有計數(shù)值,每次信號量post操作都會被記錄
互斥鎖必須是誰上鎖就由誰來解鎖,而信號量的wait和post操作不必由同一個線程執(zhí)行。
2. 互斥鎖要么被鎖住,要么被解開,和二值信號量類似
3. sem_post是各種同步技巧中,唯一一個能在信號處理程序中安全調(diào)用的函數(shù)
4. 互斥鎖是為上鎖而優(yōu)化的;條件變量是為等待而優(yōu)化的; 信號量既可用于上鎖,也可用于等待,因此會有更多的開銷和更高的復(fù)雜性
5. 互斥鎖,條件變量都只用于同一個進(jìn)程的各線程間,而信號量(有名信號量)可用于不同進(jìn)程間的同步。當(dāng)信號量用于進(jìn)程間同步時,要求信號量建立在共享內(nèi)存區(qū)。
6. 信號量有計數(shù)值,每次信號量post操作都會被記錄,而條件變量在發(fā)送信號時,如果沒有線程在等待該條件變量,那么信號將丟失。
讀寫鎖
讀寫鎖與互斥量類似,不過讀寫鎖允許更高的并行性。互斥量要么是鎖住狀態(tài)要么是不加鎖狀態(tài),而且一次只有一個線程可以對其加鎖。
讀寫鎖可以由三種狀態(tài):讀模式下加鎖狀態(tài)、寫模式下加鎖狀態(tài)、不加鎖狀態(tài)。一次只有一個線程可以占有寫模式的讀寫鎖,但是多個線程可以同時占有讀模式的讀寫
鎖。
在讀寫鎖是寫加鎖狀態(tài)時,在這個鎖被解鎖之前,所有試圖對這個鎖加鎖的線程都會被阻塞。當(dāng)讀寫鎖在讀加鎖狀態(tài)時,所有試圖以讀模式對它進(jìn)行加鎖的線程都可以得到訪問權(quán),但是如果線程希望以寫模式對此鎖進(jìn)行加鎖,它必須阻塞直到所有的線程釋放讀鎖。雖然讀寫鎖的實現(xiàn)各不相同,但當(dāng)讀寫鎖處于讀模式鎖住狀態(tài)時,如果有另外的線程試圖以寫模式加鎖,讀寫鎖通常會阻塞隨后的讀模式鎖請求。這樣可以避免讀模式鎖長期占用,而等待的寫模式鎖請求一直得不到滿足。
讀寫鎖非常適合于對數(shù)據(jù)結(jié)構(gòu)讀的次數(shù)遠(yuǎn)大于寫的情況。當(dāng)讀寫鎖在寫模式下時,它所保護(hù)的數(shù)據(jù)結(jié)構(gòu)就可以被安全地修改,因為當(dāng)前只有一個線程可以在寫模式下?lián)?有這個鎖。當(dāng)讀寫鎖在讀狀態(tài)下時,只要線程獲取了讀模式下的讀寫鎖,該鎖所保護(hù)的數(shù)據(jù)結(jié)構(gòu)可以被多個獲得讀模式鎖的線程讀取。
讀寫鎖也叫做共享-獨占鎖,當(dāng)讀寫鎖以讀模式鎖住時,它是以共享模式鎖住的;當(dāng)他以寫模式鎖住時,它是以獨占模式鎖住的。
初始化和銷毀:
#include
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
成功則返回0, 出錯則返回錯誤編號.
同互斥量以上, 在釋放讀寫鎖占用的內(nèi)存之前, 需要先通過thread_rwlock_destroy對讀寫鎖進(jìn)行清理工作, 釋放由init分配的資源.
讀和寫:
#include
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
成功則返回0, 出錯則返回錯誤編號.
這3個函數(shù)分別實現(xiàn)獲取讀鎖, 獲取寫鎖和釋放鎖的操作. 獲取鎖的兩個函數(shù)是阻塞操作, 同樣, 非阻塞的函數(shù)為:
#include
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
成功則返回0, 出錯則返回錯誤編號.
非阻塞的獲取鎖操作, 如果可以獲取則返回0, 否則返回錯誤的EBUSY.
雖然讀寫鎖提高了并行性,但是就速度而言并不比互斥量快.
可能這也是即使有讀寫鎖存在還會使用互斥量的原因,因為他在速度方面略勝一籌。這就需要我們在寫程序的時候綜合考慮速度和并行性并找到一個折中。
比如: 假設(shè)使用互斥量需要0.5秒,使用讀寫鎖需要0.8秒。在類似學(xué)生管理系統(tǒng)這類中,可能百分之九十的時間都是查詢操作,那么假如現(xiàn)在突然來個個20個請求,如果使用的是互斥量,那么最后的那個查詢請求被滿足需要10后。這樣,估計沒人能受得了。而使用讀寫鎖,應(yīng)為 讀鎖能夠多次獲得。所以所有的20個請求,每個請求都能在1秒左右得到滿足。
也就是說,在一些寫操作比較多或是本身需要同步的地方并不多的程序中我們應(yīng)該使用互斥量,而在讀操作遠(yuǎn)大于寫操作的一些程序中我們應(yīng)該使用讀寫鎖來進(jìn)行同步
條件變量(condition)
條件變量與互斥量一起使用時,允許線程以無競爭的方式等待特定的條件發(fā)生。
條件本身是由互斥量保護(hù)的。線程在改變條件狀態(tài)前必須首先鎖住互斥量,其它線程在獲得互斥量之前不會察覺到這種改變,因此必須鎖定互斥量以后才能計算條件。
條件的檢測是在互斥鎖的保護(hù)下進(jìn)行的。如果一個條件為假,一個線程自動阻塞,并釋放等待狀態(tài)改變的互斥鎖。如果另一個線程改變了條件,它發(fā)信號給關(guān)聯(lián)的條件
變量,喚醒一個或多個等待它的線程,重新獲得互斥鎖,重新評價條件。如果兩進(jìn)程共享可讀寫的內(nèi)存,條件變量可以被用來實現(xiàn)這兩進(jìn)程間的線程同步。
1. 初始化:
條件變量采用的數(shù)據(jù)類型是pthread_cond_t, 在使用之前必須要進(jìn)行初始化, 這包括兩種方式:
靜態(tài): 可以把常量PTHREAD_COND_INITIALIZER給靜態(tài)分配的條件變量.
動態(tài): pthread_cond_init函數(shù), 是釋放動態(tài)條件變量的內(nèi)存空間之前, 要用pthread_cond_destroy對其進(jìn)行清理.
#include
int pthread_cond_init(pthread_cond_t *restrict cond, pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t *cond);
成功則返回0, 出錯則返回錯誤編號.
注意:條件變量占用的空間并未被釋放。
當(dāng)pthread_cond_init的attr參數(shù)為NULL時, 會創(chuàng)建一個默認(rèn)屬性的條件變量; 非默認(rèn)情況以后討論.
2. 等待條件:
#include
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restric mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict timeout);
成功則返回0, 出錯則返回錯誤編號.
這兩個函數(shù)分別是阻塞等待和超時等待.
等待條件函數(shù)等待條件變?yōu)檎? 傳遞給pthread_cond_wait的互斥量對條件進(jìn)行保護(hù), 調(diào)用者把鎖住的互斥量傳遞給函數(shù). 函數(shù)把調(diào)用線程放到等待條件的線程列表上, 然后對互斥量解鎖, 這兩個操作是原子的. 這樣 便關(guān)閉了條件檢查和線程進(jìn)入休眠狀態(tài)等待條件改變這兩個操作之間的時間通道, 這樣線程就不會錯過條件的任何變化.
當(dāng)pthread_cond_wait返回時, 互斥量再次被鎖住.
pthread_cond_wait函數(shù)的返回并不意味著條件的值一定發(fā)生了變化,必須重新檢查條件的值。
pthread_cond_wait函數(shù)返回時,相應(yīng)的互斥鎖將被當(dāng)前線程鎖定,即使是函數(shù)出錯返回。
阻塞在條件變量上的線程被喚醒以后,直到pthread_cond_wait()函數(shù)返回之前條件的值都有可能發(fā)生變化。所以函數(shù)返回以后,在鎖定相應(yīng)的互斥鎖之前,必須重新測試條 件值。更好的測試方法是循環(huán)調(diào)用pthread_cond_wait函數(shù),并把滿足條件的表達(dá)式置為循環(huán)的終止條件。如:
pthread_mutex_lock();
while (condition_is_false)
pthread_cond_wait();
pthread_mutex_unlock();
阻塞在同一個條件變量上的不同線程被釋放的次序是不一定的。
注意:pthread_cond_wait()函數(shù)是退出點,如果在調(diào)用這個函數(shù)時,已有一個掛起的退出請求,且線程允許退出,這個線程將被終止并開始執(zhí)行善后處理函數(shù),而這時和條 件變量相關(guān)的互斥鎖仍將處在鎖定狀態(tài)。
pthread_cond_timedwait函數(shù)到了一定的時間,即使條件未發(fā)生也會解除阻塞。這個時間由參數(shù)abstime指定。函數(shù)返回時,相應(yīng)的互斥鎖往往是鎖定的,即使是函數(shù)出錯返回。
注意:pthread_cond_timedwait函數(shù)也是退出點。
超時時間參數(shù)是指一天中的某個時刻。使用舉例:
pthread_timestruc_t to;
to.tv_sec = time(NULL) + TIMEOUT;
to.tv_nsec = 0;
超時返回的錯誤碼是ETIMEDOUT。
3. 通知條件:
#include
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
成功則返回0, 出錯則返回錯誤編號.
這兩個函數(shù)用于通知線程條件已經(jīng)滿足. 調(diào)用這兩個函數(shù), 也稱向線程或條件發(fā)送信號. 必須注意, 一定要在改變條件狀態(tài)以后再給線程發(fā)送信號.
linux seminit的介紹就聊到這里吧,感謝你花時間閱讀本站內(nèi)容,更多關(guān)于linux seminit,Linux Seminit:管理和同步信號量的關(guān)鍵,linux 信號燈中線程切換問題,如何對讀寫鎖進(jìn)行處理的信息別忘了在本站進(jìn)行查找喔。
香港服務(wù)器選創(chuàng)新互聯(lián),2H2G首月10元開通。
創(chuàng)新互聯(lián)(www.cdcxhl.com)互聯(lián)網(wǎng)服務(wù)提供商,擁有超過10年的服務(wù)器租用、服務(wù)器托管、云服務(wù)器、虛擬主機、網(wǎng)站系統(tǒng)開發(fā)經(jīng)驗。專業(yè)提供云主機、虛擬主機、域名注冊、VPS主機、云服務(wù)器、香港云服務(wù)器、免備案服務(wù)器等。
當(dāng)前題目:LinuxSeminit:管理和同步信號量的關(guān)鍵(linuxseminit)
本文URL:http://www.fisionsoft.com.cn/article/cdpcied.html


咨詢
建站咨詢
