Linux 多线程中互斥量与条件变量的使用小结
首先,为了使得全局在变量线程中进行写操作时能够不发生混乱,即不能有多个线程同时写同一个变量,于是有了互斥量的概念。即定义为互斥量的变量才能加锁。即在一个线程使用该变量时先给变量加锁,用完给变量解锁,若此时有其他线程也同时想要使用该变量时,则需要变量为空闲状态,即不加锁状态时才能使用,否则会进入一个阻塞状态,等待该变量成为空闲态。
即有由于该原因,若该互斥量一直处于锁住状态而另一个线程一直想到调用该变量,因此线程堵塞无法正常该线程,所以为了使CPU提高运行效率,于是又引出了条件变量。
可以说条件变量是在互斥量的基础上产生的,即需要再设定一个全局变量为条件变量,在另一个一直想要使用该线程的满足条件时就立即去调用该变量并自动加锁,用完再使满足其原有线程的条件,于是就原线程便可继续使用该变量。
可以通过使用pthread_con_wait函数,作用是等待条件变量成为真。调用者会把锁住的互斥量传递给函数。(即换一个线程锁住变量) 然后待条件符合时调用函数(至少唤醒等待条件的某一个线程)pthread_cond_signal(pthread_con_t *cond);
注:条件变量是配合互斥量使用的 init与destory必须成对出现 所以若需要在多线程使用条件变量则可分为以下几个步骤:
mutex_init
cond1_init
cond2_init
thread1{
cond2_wait
cond2_signal
}
thread2{
cond1_wait
cond1_signal
}
cond1_destory
cond2_destory
mutex_destory
===========这里展现一个奇特的效果
先贴代码
1 #include <stdio.h>
2 #include <string.h>
3 #include <pthread.h>
4 #include <unistd.h>
5 #include <stdlib.h>
6 #include <signal.h>
7 #include <stddef.h>
8 #include "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h"
9
10 int pro;
11 pthread_mutex_t lock;
12 pthread_cond_t notempty;
13 pthread_cond_t notfull;
14
15 void thread_init(void)
16 {
17 int ini1,ini2,ini3;
18
19 ini1=pthread_mutex_init(&lock,NULL);
20
21 ini2=pthread_cond_init(¬empty,NULL);
22 ini3=pthread_cond_init(¬full,NULL);
23
24 if( ini1 && ini2 && ini3)
25 {
26 printf("init failed,%d,%d,%d\n",ini1,ini2,ini3);
27 }else
28 printf("init success\n");
29 return;
30 }
31
32 void destory(void)
33 {
34 int des1,des2,des3;
35
36 des1= pthread_cond_destroy(¬empty);
37
38 des2= pthread_cond_destroy(¬full);
39
40 des3=pthread_mutex_destroy(&lock);
41
42 if(!des1 || !des2 || !des3)
43 {
44 printf("destroy failed\n");
45 }else
46 printf("destroy succeed\n");
47 return;
48 }
49
50 void *consumer(void *arg)
51 {
52 int sig=0;
53 printf("welcome consume\n");
54
55 int err=pthread_mutex_lock(&lock);
56 if(err==0)
57 printf(" producer lock succeed ,number:%d\n",pro);
58 else
59 printf("lock failed\n");
60
61
62 while(pro)
63 printf("consume%d\n",--pro);
64
65 if(pro==0)
66 {
67 pthread_cond_signal(¬full);
68 printf("turning to producer..\n");
69 int con=pthread_cond_wait(¬empty,&lock);
70 if(con==0)
71 printf("consumer waiting\n");
72 }
73
74
75 pthread_mutex_unlock(&lock);
76
77 return NULL;
78 }
79
80 void *producer(void * arg)
81 {
82 printf("this is producer\n");
83
84
85 int err=pthread_mutex_lock(&lock);
86 if(err==0)
87 printf(" producer lock succeed ,number:%d\n",pro);
88 else
89 printf("lock failed\n");
90
91
92 while(pro<8)
93 {
94 printf("produce%d\n",pro++);
95 if(pro==8)
96 {
97 pthread_cond_signal(¬empty);
98 printf("turning to consumer..\n");
99
100 int con=pthread_cond_wait(¬full,&lock);
101 if(con !=0)
102 printf("consuming\n");
103 printf("here is produce_wait\n");
104 break;
105 }
106 }
107
108 pthread_mutex_unlock(&lock);
109
110 return NULL;
111 }
112
113 int main()
114 {
115 pthread_t tid1,tid2;
116
117 int err;
118 pro=0;
119
120
121
122 err=pthread_create(&tid1,NULL,consumer,NULL);
123 if(err != 0)
124 {
125 printf("thre1 create failed\n");
126
127 return -1;
128 }
129 err=pthread_create(&tid2,NULL,producer,NULL);
130 if(err != 0)
131 {
132 printf("thre1 create failed\n");
133
134 return -1;
135 }
136
137 thread_init();
138
139 sleep(8);
140 pthread_join(tid1,NULL);
141 pthread_join(tid2,NULL);
142
143
144 destory();
145
146 return 0;
147 }
再来看下结果图 我这边使用的时两个线程,模仿的是消费者与生产者的框架,当生产者生产完毕,传递给消费者线程信号,于是程序进入到消费者线程【第一次进入】,生产者线程此时在等待信号,然后消费者消费完毕,传达给生产者信号,于是程序进入生产者进程【第二次】,注意此时的程序并没有从开始运行该线程,而是跳到其等待的地方。于是应该在wait函数后面与signal函数中间写需要处理的代码。
修改程序如下:
void *consumer(void *arg)
{
int sig=0;
printf("welcome consume\n");
while(1)
{
int err=pthread_mutex_lock(&lock);
if(err==0)
printf(" producer lock succeed ,number\n");
else
printf("lock failed\n");
while(pro == 0)
{
printf("consumer waiting\n");
int con=pthread_cond_wait(¬empty,&lock);
if(con==0)
printf("consumer wait back\n");
else
printf("wrong\n");
}
while(pro)
printf("consume%d\n",--pro);
if(pro==0)
{
pthread_cond_signal(¬full);
printf("turning to producer..\n");
pthread_mutex_unlock(&lock);
printf("con_unlock\n");
}
}
return NULL;
}
void *producer(void * arg)
{
printf("this is producer\n");
while(1)
{
int err=pthread_mutex_lock(&lock);
if(err==0)
printf(" producer lock succeed\n");
else
printf("lock failed\n");
while(pro!=0)
{
printf("producer waiting\n");
pthread_cond_wait(¬full,&lock);
printf("producer wait back\n");
}
while(pro<8)
{
printf("produce%d\n",pro++);
if(pro==8)
{
pthread_cond_signal(¬empty);
printf("turning to consumer..\n");
pthread_mutex_unlock(&lock);
printf("pro_unlock\n");
}
}
}
return NULL;
}
程序运行截图如下:
|