簡單來說 thread 最常遇到的問題就是共用資源分配的問題,當你設計multi-threads時有特別是利用到global variable (全域變數時),要特別注意同步及資源的問題(Race Condition、Critical Section),否則很容易對你自己create 的 thread 無法掌握,造成 random issues。
Mutex 常用 API
pthread_mutex_init() 初始化互斥鎖
pthread_mutex_destroy() 刪除互斥鎖
pthread_mutex_lock():占有互斥鎖(阻塞操作)
pthread_mutex_trylock():試圖占有互斥鎖(不阻塞操作)。即,當互斥鎖空閒時,將占有該鎖;否則,立即返回。
具體說一下trylock函數, 這個函數是非阻塞呼叫模式, 也就是說, 如果互斥量沒被鎖住, trylock函數將把互斥量加鎖, 並獲得對共享資源的訪問權限; 如果互斥量被鎖住了, trylock函數將不會阻塞等待而直接返回EBUSY, 表示共享資源處於忙狀態。
pthread_mutex_unlock(): 釋放互斥鎖
由 example-1 可以觀察到 mutex API 簡單的範例,創建兩個threads對sum從1加到100。前面第一個線程從1-49,后面從50-100。主線程讀取最后的加值。為了防止資源競爭,用了pthread_mutex_t 鎖操作。
example-1中主程式中有一段 sleep(1),可以觀察到若沒有加入讓他主程式delay 一會,得到的結果不會是預想的結果從1累加到100,這也是設計thread時必須考慮到的。
Example-1
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
typedef struct ct_sum
{ int sum;
pthread_mutex_t lock;
}ct_sum;
void * add1(void * cnt)
{
printf("pthread add1 !!\n");
pthread_mutex_lock(&(((ct_sum*)cnt)->lock));
printf("pthread add1 get key!!\n");
int i;
for( i=0;i<50;i++){
(*(ct_sum*)cnt).sum+=i;
}
pthread_mutex_unlock(&(((ct_sum*)cnt)->lock));
pthread_exit(NULL);
return 0;
}
void * add2(void *cnt)
{
printf("pthread add2 !!\n");
int i;
cnt= (ct_sum*)cnt;
pthread_mutex_lock(&(((ct_sum*)cnt)->lock));
printf("pthread add2 get key!!\n");
for( i=50;i<101;i++)
{
(*(ct_sum*)cnt).sum+=i;
}
pthread_mutex_unlock(&(((ct_sum*)cnt)->lock));
pthread_exit(NULL);
return 0;
}
int main(void)
{ int i;
pthread_t ptid1,ptid2;
int sum=0;
ct_sum cnt;
pthread_mutex_init(&(cnt.lock),NULL);
cnt.sum=0;
pthread_create(&ptid1,NULL,add1,&cnt);
pthread_create(&ptid2,NULL,add2,&cnt);
//sleep(1);
pthread_mutex_lock(&(cnt.lock));
printf("main proccess get key!!\n");
printf("sum %d\n", cnt.sum);
pthread_mutex_unlock(&(cnt.lock));
pthread_join(ptid1,NULL);
printf("join ptid1\n");
pthread_join(ptid2,NULL);
printf("join ptid2\n");
pthread_mutex_destroy(&(cnt.lock));
return 0;
}
reference:wiki_pthread、h's 手扎_pthread、 立你斯學習紀錄-pthread mutex
pthread_mutex_lock():占有互斥鎖(阻塞操作)
pthread_mutex_trylock():試圖占有互斥鎖(不阻塞操作)。即,當互斥鎖空閒時,將占有該鎖;否則,立即返回。
具體說一下trylock函數, 這個函數是非阻塞呼叫模式, 也就是說, 如果互斥量沒被鎖住, trylock函數將把互斥量加鎖, 並獲得對共享資源的訪問權限; 如果互斥量被鎖住了, trylock函數將不會阻塞等待而直接返回EBUSY, 表示共享資源處於忙狀態。
pthread_mutex_unlock(): 釋放互斥鎖
由 example-1 可以觀察到 mutex API 簡單的範例,創建兩個threads對sum從1加到100。前面第一個線程從1-49,后面從50-100。主線程讀取最后的加值。為了防止資源競爭,用了pthread_mutex_t 鎖操作。
example-1中主程式中有一段 sleep(1),可以觀察到若沒有加入讓他主程式delay 一會,得到的結果不會是預想的結果從1累加到100,這也是設計thread時必須考慮到的。
Example-1
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
typedef struct ct_sum
{ int sum;
pthread_mutex_t lock;
}ct_sum;
void * add1(void * cnt)
{
printf("pthread add1 !!\n");
pthread_mutex_lock(&(((ct_sum*)cnt)->lock));
printf("pthread add1 get key!!\n");
int i;
for( i=0;i<50;i++){
(*(ct_sum*)cnt).sum+=i;
}
pthread_mutex_unlock(&(((ct_sum*)cnt)->lock));
pthread_exit(NULL);
return 0;
}
void * add2(void *cnt)
{
printf("pthread add2 !!\n");
int i;
cnt= (ct_sum*)cnt;
pthread_mutex_lock(&(((ct_sum*)cnt)->lock));
printf("pthread add2 get key!!\n");
for( i=50;i<101;i++)
{
(*(ct_sum*)cnt).sum+=i;
}
pthread_mutex_unlock(&(((ct_sum*)cnt)->lock));
pthread_exit(NULL);
return 0;
}
int main(void)
{ int i;
pthread_t ptid1,ptid2;
int sum=0;
ct_sum cnt;
pthread_mutex_init(&(cnt.lock),NULL);
cnt.sum=0;
pthread_create(&ptid1,NULL,add1,&cnt);
pthread_create(&ptid2,NULL,add2,&cnt);
//sleep(1);
pthread_mutex_lock(&(cnt.lock));
printf("main proccess get key!!\n");
printf("sum %d\n", cnt.sum);
pthread_mutex_unlock(&(cnt.lock));
pthread_join(ptid1,NULL);
printf("join ptid1\n");
pthread_join(ptid2,NULL);
printf("join ptid2\n");
pthread_mutex_destroy(&(cnt.lock));
return 0;
}
reference:wiki_pthread、h's 手扎_pthread、 立你斯學習紀錄-pthread mutex
沒有留言:
張貼留言