執行緒間的同步互斥學習
阿新 • • 發佈:2018-12-12
寫在最前面
華清遠見教育集團
15年專注高階IT培訓
做良心教育,做專業教育,做受人尊敬的職業教育創客學院官網:http://www.makeru.com.cn/
華清遠見創客學院嵌入式課程連結:http://www.makeru.com.cn/emb
華清遠見創客學院物聯網課程連結:http://www.makeru.com.cn/iot
正文
個人認為各個執行緒執行的任務有所不同,但是本質上都是對資料的處理,而資料脫離了專案去分析好像沒有啥意義。同時,多個執行緒共享一些全域性資源。為了避免不同執行緒對資源讀寫造成的衝突,那我們就要引入同步互斥機制。本文重點還是學習這些方法。
對於臨界資源的訪問,有同步機制和互斥機制兩種
執行緒同步機制
- 訊號量(多個)
- 條件變數+互斥鎖
執行緒互斥機制
- 訊號量(單個)
- 互斥鎖
1.訊號量實現同步
#include<stdio.h> #include <pthread.h> #include <semaphore.h> #define N 64 typedef struct message{ char buf[N]; int len; }msg_t; sem_t sem_reverse; sem_t sem_printf; void* reverse_msgbuf(void* arg) { msg_t *msg = (msg_t *)arg; int i = 0; char tmp; while(1){ sem_wait(&sem_reverse); //P操作 sem_reverse 申請資源(資源數減少1) printf("reverse_msgbuf -------------\n"); //printf("hello reverse_msgbuf.\n"); #if 1 for(i = 0; i < msg->len/2; i ++){ tmp = msg->buf[i]; msg->buf[i] = msg->buf[msg->len - i - 1]; msg->buf[msg->len - i -1] = tmp; } #endif sleep(1); printf("reverse_msgbuf :%s\n",msg->buf); sem_post(&sem_printf); //V操作 sem_printf 釋放資源(資源數加1) } } void* printf_msgbuf(void* arg) { msg_t *msg = (msg_t *)arg; while(1){ sem_wait(&sem_printf); //P操作 sem_printf 申請資源(資源數減少1) printf("printf_msgbuf :***********\n"); printf("printf_msgbuf :%s\n",msg->buf); sem_post(&sem_reverse); //V操作 sem_reverse 釋放資源(資源數加1) } } int main(int argc, const char *argv[]) { msg_t msg = {"123456789",9}; pthread_t tid[2]; sem_init(&sem_reverse,0,1); //申請訊號量 sem_reverse 資源數 1 sem_init(&sem_printf,0,0); //申請訊號量 sem_printf 資源數 1 pthread_create(&tid[0],NULL,reverse_msgbuf,(void *)&msg); //申請執行緒 reverse_msgbuf pthread_create(&tid[1],NULL,printf_msgbuf,(void *)&msg); pause(); return 0; }
[email protected]:~/homework/demo$ gcc test1.c -o test1 -lpthread
2.互斥鎖實現互斥
#include<stdio.h> #include <pthread.h> #define N 64 typedef struct message{ char buf[N]; int len; }msg_t; pthread_mutex_t mymutex; void* reverse_msgbuf(void* arg) { msg_t *msg = (msg_t *)arg; int i = 0; char tmp; while(1){ pthread_mutex_lock(&mymutex); for(i = 0; i < msg->len/2; i ++){ tmp = msg->buf[i]; msg->buf[i] = msg->buf[msg->len - i - 1]; msg->buf[msg->len - i -1] = tmp; } pthread_mutex_unlock(&mymutex); } } void* printf_msgbuf(void* arg) { msg_t *msg = (msg_t *)arg; while(1){ pthread_mutex_lock(&mymutex); //加鎖 printf("buf :%s\n",msg->buf); pthread_mutex_unlock(&mymutex); //解鎖 sleep(1); } } int main(int argc, const char *argv[]) { msg_t msg = {"123456789",9}; pthread_t tid[2]; pthread_mutex_init(&mymutex,NULL); //申請鎖 mymutex pthread_create(&tid[0],NULL,reverse_msgbuf,(void *)&msg); //申請執行緒 reverse_msgbuf pthread_create(&tid[1],NULL,printf_msgbuf,(void *)&msg); pause(); return 0; }
[email protected]:~/homework/demo$ gcc test2.c -o test2 -lpthread
3.條件鎖實現同步 "pthread_cond_broadcast 喚醒"
#include<stdio.h>
#include <pthread.h>
#define N 64
typedef struct message{
char buf[N];
int len;
// int busy_flag;
}msg_t;
int flag = 0;
pthread_mutex_t mymutex;
pthread_cond_t mycond = PTHREAD_COND_INITIALIZER;
void* reverse_msgbuf(void* arg)
{
msg_t *msg = (msg_t *)arg;
int i = 0;
char tmp;
while(1){
pthread_mutex_lock(&mymutex);
printf("reverse_msgbuf -------------\n");
while(flag != 0){
pthread_cond_wait(&mycond,&mymutex); //解鎖互斥鎖,執行緒阻塞
}
//printf("hello reverse_msgbuf.\n");
#if 1
for(i = 0; i < msg->len/2; i ++){
tmp = msg->buf[i];
msg->buf[i] = msg->buf[msg->len - i - 1];
msg->buf[msg->len - i -1] = tmp;
}
#endif
printf("reverse_msgbuf :%s\n",msg->buf);
flag = 1; //更新 flag =1
pthread_mutex_unlock(&mymutex);
pthread_cond_broadcast(&mycond); //通過廣播喚醒另一個執行緒的 pthread_cond_wait
}
}
void* printf_msgbuf(void* arg)
{
msg_t *msg = (msg_t *)arg;
while(1){
pthread_mutex_lock(&mymutex);
printf("printf_msgbuf :***********\n");
while(flag != 1){
pthread_cond_wait(&mycond,&mymutex);
}
printf("printf_msgbuf :%s\n",msg->buf);
flag = 0; //更新變數 flag = 0
pthread_mutex_unlock(&mymutex);
pthread_cond_broadcast(&mycond); //通過廣播喚醒另一個執行緒的 pthread_cond_wait
}
}
int main(int argc, const char *argv[])
{
//msg_t msg = {"123456789",9,0};
msg_t msg = {"123456789",9};
pthread_t tid[2];
pthread_cond_init(&mycond,NULL); //申請條件鎖
pthread_mutex_init(&mymutex,NULL); //申請互斥鎖
pthread_create(&tid[0],NULL,reverse_msgbuf,(void *)&msg); //申請執行緒
pthread_create(&tid[1],NULL,printf_msgbuf,(void *)&msg); //申請執行緒
pause();
return 0;
}
[email protected]:~/homework/demo$ gcc test3.c -o test3 -lpthread
4.條件鎖實現同步 "pthread_cond_signal 喚醒"
#include<stdio.h>
#include <pthread.h>
#define N 64
typedef struct message{
char buf[N];
int len;
// int busy_flag;
}msg_t;
pthread_mutex_t mymutex;
pthread_cond_t mycond_reverse = PTHREAD_COND_INITIALIZER;
pthread_cond_t mycond_printf = PTHREAD_COND_INITIALIZER;
void* reverse_msgbuf(void* arg)
{
msg_t *msg = (msg_t *)arg;
int i = 0;
char tmp;
while(1){
pthread_mutex_lock(&mymutex);
pthread_cond_wait(&mycond_reverse,&mymutex);
printf("reverse_msgbuf -------------\n");
#if 1
for(i = 0; i < msg->len/2; i ++){
tmp = msg->buf[i];
msg->buf[i] = msg->buf[msg->len - i - 1];
msg->buf[msg->len - i -1] = tmp;
}
#endif
printf("reverse_msgbuf :%s\n",msg->buf);
pthread_mutex_unlock(&mymutex);
}
}
void* printf_msgbuf(void* arg)
{
msg_t *msg = (msg_t *)arg;
while(1){
pthread_mutex_lock(&mymutex);
pthread_cond_wait(&mycond_printf,&mymutex);
printf("printf_msgbuf :***********\n");
printf("printf_msgbuf :%s\n",msg->buf);
pthread_mutex_unlock(&mymutex);
}
}
int main(int argc, const char *argv[])
{
//msg_t msg = {"123456789",9,0};
msg_t msg = {"123456789",9};
pthread_t tid[2];
pthread_cond_init(&mycond_printf,NULL);
pthread_cond_init(&mycond_reverse,NULL); //條件鎖
pthread_mutex_init(&mymutex,NULL); //互斥鎖
pthread_create(&tid[0],NULL,reverse_msgbuf,(void *)&msg);
pthread_create(&tid[1],NULL,printf_msgbuf,(void *)&msg); //申請執行緒
while(1){
pthread_cond_signal (&mycond_printf); //喚醒 mycond_printf
sleep(1);
pthread_cond_signal (&mycond_reverse); //喚醒 mycond_reverse
sleep(1);
}
pause();
return 0;
}
[email protected]:~/homework/demo$ gcc test4.c -o test4 -lpthread