IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> Linux&嵌入式学习 -> 正文阅读

[嵌入式]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;
}

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

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-08-07 12:15:04  更:2021-08-07 12:16:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 20:54:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码