- 在代碼中使用pthread沉帮,進(jìn)行編譯時(shí),需要使用命令 g++ -o hello hello.c -lpthread
- Makefile怎么寫鞍盗?
互斥鎖
互斥鎖只有兩種狀態(tài)随橘,鎖定和非鎖定
頭文件:<pthread.h>
類型:pthread_mutex_t
- pthread_mutex_lock:加鎖还栓。如果鎖已經(jīng)被占有,則該線程加入一個(gè)隊(duì)列中。
- pthread_mutex_trylock:嘗試加鎖背传,如果鎖已被占有呆瞻,則線程不加入隊(duì)列,而是返回錯(cuò)誤径玖。
- pthread_mutex_unlock:釋放鎖
例程
- 5個(gè)線程互斥顯示數(shù)組數(shù)字痴脾,當(dāng)其中一個(gè)線程在顯示時(shí),其他線程無(wú)法顯示梳星,直接退出
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
// 聲明并且初始化鎖(互斥鎖)
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
int tf[5];
void* print(void* i)
{
/********************************************
* 如果改為 int flag = pthread_mutex_lock(&mut);
* 則為阻塞的,該線程會(huì)被加入隊(duì)列等待開鎖
********************************************/
/**************************************************
* 非阻塞如果不為零說明有其他線程正在進(jìn)行,即不應(yīng)該執(zhí)行該線程
* 因此可以判斷flag并退出該線程
**************************************************/
int *id = (int*)i;
int flag = pthread_mutex_trylock(&mut);
if (flag==0)
{
sleep(1);
for (int j=0;j<5;j++)
printf("thread %d: %d\n", *id, j);
pthread_mutex_unlock(&mut);
}
else
{
printf("thread %d: 其他線程正在進(jìn)行\(zhòng)n", *id);
}
}
int main()
{
pthread_t td[5]; // 初始化線程
for(int i=0;i<5;i++)
tf[i] = i;
for(int i=0;i<5;i++)
// 創(chuàng)建線程
pthread_create(&td[i],NULL,print,(void *)&tf[i]);
for(int i=0;i<5;i++)
{
// 運(yùn)行線程,join函數(shù)確保子線程執(zhí)行完了主程序才退出
pthread_join(td[i],NULL);
}
pthread_mutex_destroy(&mut);
}
條件鎖
條件鎖就是所謂的條件變量赞赖,某一個(gè)線程因?yàn)槟硞€(gè)條件為滿足時(shí)可以使用條件變量使改程序處于阻塞狀態(tài)。一旦條件滿足以“信號(hào)量”的方式喚醒一個(gè)因?yàn)樵摋l件而被阻塞的線程冤灾。
頭文件:<pthread.h>
類型:pthread_cond_t
- pthread_cond_wait:線程阻塞在條件變量
- pthread_cond_signal:線程被喚醒
linux C++ 多線程使用pthread_cond 條件變量
線程屬性pthread_attr_t簡(jiǎn)介
例程
- 線程0前域、線程1互斥加一個(gè)數(shù),加一次喚醒一次條件觸發(fā)的線程2韵吨,如果線程2處于阻塞等待狀態(tài)則被喚醒
- 線程2判斷數(shù)值大小時(shí)匿垄,給線程0、1上鎖归粉,停止加數(shù)年堆,當(dāng)數(shù)字小于10時(shí),等待3秒盏浇,否則加100退出該線程
- 線程0变丧、1各加10次退出線程,線程2檢測(cè)到數(shù)字大于10加100后退出線程绢掰,三個(gè)線程都結(jié)束程序退出
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#define NUM_THREADS 3
#define TCOUNT 10
#define COUNT_LIMIT 10
int count = 0;
int thread_ids[3] = {0,1,2};
pthread_mutex_t count_mutex; // 計(jì)數(shù)時(shí)上鎖
pthread_cond_t count_threshold_cv;
void *inc_count(void *idp)
{
int i = 0;
int taskid = 0;
int *my_id = (int*)idp;
for (i=0; i<TCOUNT; i++) {
// 互斥鎖上鎖
pthread_mutex_lock(&count_mutex);
taskid = count;
count++;
/*
喚醒一個(gè)阻塞在該條件變量的線程
如果沒有線程被阻塞在條件變量上痒蓬,那么調(diào)用pthread_cond_signal()將沒有作用
*/
pthread_cond_signal(&count_threshold_cv);
printf("inc_count(): thread %d, count = %d, 開互斥鎖\n", *my_id, count);
// 互斥鎖解鎖
pthread_mutex_unlock(&count_mutex);
sleep(1);
}
printf("inc_count(): thread %d, Threshold reached.\n", *my_id);
pthread_exit(NULL);
}
void *watch_count(void *idp)
{
int *my_id = (int*)idp;
printf("Starting watch_count(): thread %d\n", *my_id);
pthread_mutex_lock(&count_mutex);
while(count<COUNT_LIMIT) {
sleep(3);
/*
函數(shù)將自動(dòng)/原子到解鎖mutex參數(shù)指向的互斥鎖,
并使當(dāng)前線程阻塞在cv參數(shù)指向的條件變量上
被阻塞的線程可以被pthread_cond_signal函數(shù)滴劲,
pthread_cond_broadcast函數(shù)喚醒攻晒,
也可能在被信號(hào)中斷后被喚醒
pthread_cond_wait函數(shù)的返回并不意味著條件的值一定發(fā)生了變化,
必須重新檢查條件的值.
本例子中使用類COUNT_LIMIT最為滿足條件的值
pthread_cond_wait函數(shù)返回時(shí)班挖,相應(yīng)的互斥鎖將被當(dāng)前線程鎖定鲁捏,
即使是函數(shù)出錯(cuò)返回
*/
pthread_cond_wait(&count_threshold_cv, &count_mutex);
printf("watch_count(): thread %d 收到條件信號(hào).\n", *my_id);
}
count += 100;
pthread_mutex_unlock(&count_mutex);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
int i, rc;
pthread_t threads[3];
pthread_attr_t attr; // 線程屬性
/* Initialize mutex and condition variable objects */
pthread_mutex_init(&count_mutex, NULL);
pthread_cond_init (&count_threshold_cv, NULL);
/* For portability, explicitly create threads in a joinable state */
pthread_attr_init(&attr); // 對(duì)線程屬性變量的初始化
/*
設(shè)置線程detachstate屬性。該表示新線程是否與進(jìn)程中其他線程脫離同步萧芙,
如果設(shè)置為PTHREAD_CREATE_DETACHED則新線程不能用pthread_join()來同步给梅,
且在退出時(shí)自行釋放所占用的資源。缺省為PTHREAD_CREATE_JOINABLE狀態(tài)双揪。
這個(gè)屬性也可以在線程創(chuàng)建并運(yùn)行以后用pthread_detach()來設(shè)置动羽,
而一旦設(shè)置為PTHREAD_CREATE_DETACH狀態(tài)(不論是創(chuàng)建時(shí)設(shè)置還是運(yùn)行時(shí)設(shè)置)
則不能再恢復(fù)到PTHREAD_CREATE_JOINABLE狀態(tài)。
*/
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&threads[0], &attr, inc_count, (void *)&thread_ids[0]);
pthread_create(&threads[1], &attr, inc_count, (void *)&thread_ids[1]);
pthread_create(&threads[2], &attr, watch_count, (void *)&thread_ids[2]);
/* Wait for all threads to complete */
for (i=0; i<NUM_THREADS; i++) {
pthread_join(threads[i], NULL);
}
printf ("Main(): Waited on %d threads. Done.\n", NUM_THREADS);
/* Clean up and exit */
pthread_attr_destroy(&attr);
pthread_mutex_destroy(&count_mutex);
pthread_cond_destroy(&count_threshold_cv);
pthread_exit(NULL);
return 0;
}
自旋鎖
當(dāng)發(fā)生阻塞時(shí)渔期,互斥鎖可以讓CPU去處理其他的任務(wù)运吓;而自旋鎖讓CPU一直不斷循環(huán)請(qǐng)求獲取這個(gè)鎖渴邦,它會(huì)一直占用CPU請(qǐng)求這個(gè)自旋鎖使得CPU不能去做其他的事情,直到獲取這個(gè)鎖為止拘哨,比較耗費(fèi)CPU
頭文件:<pthread.h>
類型:pthread_spinlock_t
- 初始化:pthread_spin_init(pthread_spinlock_t *__lock, int __pshared);
- pthread_spin_lock(x); //只有在獲得鎖的情況下才返回谋梭,否則一直“自旋”
- pthread_spin_trylock(x); //如果該鎖已經(jīng)被爭(zhēng)用,那么該函數(shù)立即返回一個(gè)非0值倦青,而不會(huì)自旋等待鎖被釋放;
- 釋放鎖:phtread_spin_unlock(x);
- 釋放資源:pthread_spin_destroy(&lock);
注意:自旋鎖適合于短時(shí)間的的輕量級(jí)的加鎖機(jī)制
代碼同互斥鎖瓮床,更改init、lock姨夹、unlock纤垂、destroy即可