1. 背景知識(shí):
多線程中經(jīng)常需要使用到鎖(pthread_mutex_t)來完成多個(gè)線程之間的某些同步操作
? 互斥鎖:為了使不同線程互斥的使用某個(gè)資源
○ 鎖的創(chuàng)建:pthread_mutex_init
§ pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
§ int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t * attr);
○ 鎖的屬性:
pthread_mutexattr_init(pthread_mutexattr_t *mattr)
pthread_mutexattr_settype(pthread_mutexattr_t *attr , int type)
pthread_mutexattr_gettype(pthread_mutexattr_t *attr , int *type)
§ 普通鎖:PTHREAD_MUTEX_TIMED_NP(當(dāng)一個(gè)線程加鎖以后,其余請(qǐng)求鎖的線程將形成一個(gè)等待隊(duì)列争舞,并在解鎖后按優(yōu)先級(jí)獲得鎖翩迈。這種鎖策略保證了資源分配的公平性)
§ 嵌套鎖:PTHREAD_MUTEX_RECURSIVE_NP(允許同一個(gè)線程對(duì)同一個(gè)鎖成功獲得多次,并通過多次unlock解鎖絮缅。如果是不同線程請(qǐng)求,則在加鎖線程解鎖時(shí)重新競(jìng)爭(zhēng))
§ 檢錯(cuò)鎖:PTHREAD_MUTEX_ERRORCHECK_NP(如果同一個(gè)線程請(qǐng)求同一個(gè)鎖呼股,則返回EDEADLK耕魄,否則與PTHREAD_MUTEX_TIMED_NP類型動(dòng)作相同。這樣就保證當(dāng)不允許多次加鎖時(shí)不會(huì)出現(xiàn)最簡(jiǎn)單情況下的死鎖)
§ 適應(yīng)鎖:PTHREAD_MUTEX_ADAPTIVE_NP(動(dòng)作最簡(jiǎn)單的鎖類型彭谁,僅等待解鎖后重新競(jìng)爭(zhēng))
○ 鎖的釋放:pthread_mutex_destory
○ 鎖操作:
§ 加鎖:int pthread_mutex_lock(pthread_mutex_t *mutex)
§ 解鎖:int pthread_mutex_unlock(pthread_mutex_t *mutex)
§ 測(cè)試加鎖:int pthread_mutex_trylock(pthread_mutex_t *mutex)
? 條件鎖:為了保證不同線程之間有順序(通過條件控制)地完成某個(gè)流程
○ 等待方式:
§ 無條件等待:pthread_cond_wait()
§ 計(jì)時(shí)等待:pthread_cond_timedwait()
○ 激活條件:
§ int pthread_cond_signal(pthread_cond_t *cond); 激活一個(gè)等待該條件的線程吸奴,存在多個(gè)等待線程時(shí)按入隊(duì)順序激活其中一個(gè)
§ int pthread_cond_broadcast(pthread_cond_t *cond); 激活所有等待線程
互斥鎖:
#include <pthread.h>
#include <stdio.h>
pthread_mutex_t mutex ;
void *print_msg(void *arg){
int i=0;
pthread_mutex_lock(&mutex);
for(i=0;i<15;i++){
printf("output : %d\n",i);
usleep(100);
}
pthread_mutex_unlock(&mutex);
}
int main(int argc,char** argv){
pthread_t id1;
pthread_t id2;
pthread_mutex_init(&mutex,NULL);
pthread_create(&id1,NULL,print_msg,NULL);
pthread_create(&id2,NULL,print_msg,NULL);
pthread_join(id1,NULL);
pthread_join(id2,NULL);
pthread_mutex_destroy(&mutex);
return 1;
}
條件鎖:
//一個(gè)生產(chǎn)者消費(fèi)者模型
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>
#include <unistd.h>
typedef struct node
{
int num;
struct node *next;
} node_t;
typedef node_t *list_t;
list_t head = NULL;
pthread_mutex_t mutex =
PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond =
PTHREAD_COND_INITIALIZER;
//消費(fèi)者線程
void *consume(void *arg)
{
node_t *tmp;
while (1)
{
//加鎖
pthread_mutex_lock(&mutex); //對(duì)臨界變量加鎖
if (head == NULL) //如果頭部指向空,等待
pthread_cond_wait(&cond, &mutex);
tmp = head; //將要?jiǎng)h除的節(jié)點(diǎn)賦值給中間值,然后頭指針指向下一個(gè)
head = head->next; //
//解鎖
pthread_mutex_unlock(&mutex);
//消費(fèi)tmp節(jié)點(diǎn)
printf("consum:%d\n", tmp->num);
free(tmp);
tmp = NULL;
sleep(rand() % 5);
}
}
//生產(chǎn)者線程
void *product(void *arg)
{ //函數(shù)的格式void *(*start_routine) (void *)则奥,返回值是指針考润,參數(shù)也是
node_t *n;
while (1)
{
//生產(chǎn)一個(gè)新的節(jié)點(diǎn)
n = (node_t *)malloc(sizeof(node_t));
n->num = rand() % 1000 + 1;
printf("p:%d\n", n->num);
//加鎖
pthread_mutex_lock(&mutex);
//將新節(jié)點(diǎn)放入到鏈表的頭部
n->next = head;
head = n;
//解鎖
pthread_mutex_unlock(&mutex);
//通知消費(fèi)者
pthread_cond_signal(&cond);
sleep(rand() % 5);
}
}
int main(void)
{
pthread_t pid, cid;
//設(shè)置隨機(jī)數(shù)的種子
srand(time(NULL));
//創(chuàng)建兩個(gè)線程,用于生產(chǎn)者和消費(fèi)者
pthread_create(&pid, NULL, product, NULL); //創(chuàng)建線程后即執(zhí)行該線程
pthread_create(&cid, NULL, consume, NULL); //參數(shù)含義是(存放ID的緩存區(qū)读处,NULL缺省屬性糊治,線程的執(zhí)行函數(shù),函數(shù)的唯一參數(shù))
//等待線程的匯合
pthread_join(pid, NULL);
pthread_join(cid, NULL);
//銷毀mutex鎖
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
return 0;
}