Linux&嵌入式学习

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         //mutex init
 19         ini1=pthread_mutex_init(&lock,NULL);
 20         //cond init
 21         ini2=pthread_cond_init(&notempty,NULL);
 22         ini3=pthread_cond_init(&notfull,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         //destory cond
 36         des1= pthread_cond_destroy(&notempty);
 37         //destory cond
 38         des2= pthread_cond_destroy(&notfull);
 39          //destory mutexi
 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         //lock
 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         // appoint condition
 62         while(pro)
 63         printf("consume%d\n",--pro);
 64 
 65         if(pro==0)
 66         {
 67         pthread_cond_signal(&notfull);
 68         printf("turning to producer..\n");
 69         int con=pthread_cond_wait(&notempty,&lock);
 70         if(con==0)
 71         printf("consumer waiting\n");
 72         }
 73 
 74         //unlock
 75         pthread_mutex_unlock(&lock);
 76 
 77         return NULL;
 78 }
 79 //this thread will first execute
 80 void *producer(void * arg)
 81 {
 82         printf("this is producer\n");
83 
 84         //lock
 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         // appoint condition:if buf[i]>30,meet condition and use cond_signal() to wake the thread which waits to use 
 92         while(pro<8)
 93         {
 94         printf("produce%d\n",pro++);
 95         if(pro==8)
 96         {
 97                 pthread_cond_signal(&notempty);
 98                 printf("turning to consumer..\n");
 99 
100                 int con=pthread_cond_wait(&notfull,&lock);
101                 if(con !=0)
102                         printf("consuming\n");
103                 printf("here is produce_wait\n");
104                 break;
105         }
106         }
107         //unlock
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         //the last define always first execute
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         //define a mutex,condition and init
137         thread_init();
138 
139         sleep(8);
140         pthread_join(tid1,NULL);
141         pthread_join(tid2,NULL);
142 
143         //thread finish , destory mutex and condition
144         destory();
145 
146         return 0;
147	}

再来看下结果图
在这里插入图片描述
我这边使用的时两个线程,模仿的是消费者与生产者的框架,当生产者生产完毕,传递给消费者线程信号,于是程序进入到消费者线程【第一次进入】,生产者线程此时在等待信号,然后消费者消费完毕,传达给生产者信号,于是程序进入生产者进程【第二次】,注意此时的程序并没有从开始运行该线程,而是跳到其等待的地方。于是应该在wait函数后面与signal函数中间写需要处理的代码。

修改程序如下:

void *consumer(void *arg)
{
	int sig=0;
	printf("welcome consume\n");
	
	 while(1)
	 {

	//lock
        int err=pthread_mutex_lock(&lock);
	
	if(err==0)
	 printf(" producer lock succeed ,number\n");
        else
	 printf("lock failed\n");
	
	//while pro==0 ,procedure will jump to this procedure ,by no means to waiting
	while(pro == 0)
	{
		printf("consumer waiting\n"); 
		int con=pthread_cond_wait(&notempty,&lock);
		 if(con==0)
		 printf("consumer wait back\n");
		else
			printf("wrong\n");
	}
	// appoint condition
	while(pro)
	printf("consume%d\n",--pro);

	if(pro==0)
	{
	
	pthread_cond_signal(&notfull);
	
	printf("turning to producer..\n");
	//unlock
	pthread_mutex_unlock(&lock);
	printf("con_unlock\n");

	
	}
	}

	return NULL;
}
//this thread will first execute
void *producer(void * arg)
{
	printf("this is producer\n");
			
	 while(1)
	 {

	//lock
	int err=pthread_mutex_lock(&lock);
	if(err==0)
		printf(" producer lock succeed\n");
	else
		printf("lock failed\n");
	//when pro!=0,prcedure has in this thread,by no means waiting

	while(pro!=0)
	{
		printf("producer waiting\n");

		pthread_cond_wait(&notfull,&lock);
		printf("producer wait back\n");
	}
        // appoint condition:if buf[i]>30,meet condition and use cond_signal() to wake the thread which waits to use 
        while(pro<8)
	{
  	printf("produce%d\n",pro++);
	if(pro==8)
	{
		
		pthread_cond_signal(&notempty);
		printf("turning to consumer..\n");
		//unlock
		pthread_mutex_unlock(&lock);
		printf("pro_unlock\n");
		
	}	
	}
	
	}
	return NULL;
}

程序运行截图如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值