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 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> unix环境高级编程c语言---线程竞争与同步 -> 正文阅读

[C++知识库]unix环境高级编程c语言---线程竞争与同步

线程竞争

在多线程的环境里,如果共享资源没有上锁,将会出现共享数据混乱的情况。

在单核CPU系统里,系统以时间片调度的方式让多个程序轮流使用处理器,造成了【并发】的假象。

线程同步

互斥量

int pthread_mutex_init (pthread_mutex_t* mutex,const pthread_mutexattr_t* mutexattr);
//亦可 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

int pthread_mutex_lock (pthread_mutex_t* mutex);

int pthread_mutex_unlock (pthread_mutex_t* mutex);

int pthread_mutex_destroy (pthread_mutex_t* mutex);

保证同一时间只有一个线程可以对共享资源进行操作,但是不保证同步

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

//全局变量
int n = 0;
pthread_mutex_t lock;
void *add(void *arg){
	int i;
	for(i=0;i<1000000000;i++){
		//上锁
		pthread_mutex_lock(&lock);
		++n;
		//解锁
		pthread_mutex_unlock(&lock);
	}
	return NULL;
}



int main(){
	pthread_mutex_init(&lock,NULL);//初始化互斥锁
	pthread_t id1,id2;
	int ret = pthread_create(&id1,NULL,add,NULL);
	ret = pthread_create(&id2,NULL,add,NULL);
	pthread_join(id1,NULL);
	pthread_join(id2,NULL);
	pthread_mutex_destroy(&lock);
	printf("n = %d\n",n);
	
	return 0;	
}

当不上锁的时候
在这里插入图片描述
上锁

在这里插入图片描述

信号量

信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用。在进入一个关键代码段之前,线程必须获取一个信号量;一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量。为了完成这个过程,需要创建一个信号量VI,然后将Acquire Semaphore VI以及Release Semaphore VI分别放置在每个关键代码段的首末端。确认这些信号量VI引用的是初始创建的信号量。

以一个停车场的运作为例。简单起见,假设停车场只有三个车位,一开始三个车位都是空的。这时如果同时来了五辆车,看门人允许其中三辆直接进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入外面的一辆进去,如果又离开两辆,则又可以放入两辆,如此往复。
在这个停车场系统中,车位是公共资源,每辆车好比一个线程,看门人起的就是信号量的作用。

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>

int n = 0;
sem_t sem;

void *add(void *arg){
	int i;
	for(i=0;i<1000000000;i++){
		sem_wait(&sem);//阻塞
		++n;	
		sem_post(&sem);
	}
}


int main(){
	pthread_t ids[2];
	int i,ret;
	ret = sem_init(&sem,0,1);
	if(ret == -1){
		perror("sem_init");
		return -1;
	}
	for(i=0;i<2;i++){
		ret = pthread_create(&ids[i],NULL,add,NULL);	
		if(ret != 0){
			printf("%s\n",strerror(ret));
			return -1;
		}
	}

	for(i=0;i<2;i++)
		pthread_join(ids[i],NULL);

	printf("n = %d\n",n);
	sem_destroy(&sem);//销毁
	return 0;	
}

条件变量

功能:可以更好的协调多个线程工作,使cpu不会盲目调度,需要执行的线程收到信号后则执行,收不到信号的则睡眠等待信号。 通常需要合互斥量配合使用。互斥量保证同一时间只能有一个线程工作,条件变量能指定某个线程工作

步骤:

1.对竞争部分加互斥锁 pthread_mutex_lock(&mm);

2.用while循环判断标志位,保证线程是收到信号后被唤醒的

while(flag!=0) {pthread_cond_wait(&no_ok,&mm); }

操作函数部分

3.更改标志位 :flag

4.解锁 pthread_mutex_unlock(&mm);

5.发送信号:pthread_cond_signal() 或 pthread_cond_broadcast()

在这里插入图片描述
通过缓冲区隔离生产者和消费者,与二者直连相比,避免相互等待,提高运行效率。
生产快于消费,缓冲区满,撑死。
消费快于生产,缓冲区空,饿死。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <stdbool.h>
#include <time.h>

#define MAX_SIZE 10
char vect[MAX_SIZE];  //仓库
int size = 0;         //仓库中数据的数量

pthread_mutex_t lock; //互斥锁 
pthread_cond_t notfull; //条件变量  仓库不满的条件
pthread_cond_t notempty;//条件变量  一定要结合互斥锁使用  仓库不为空的条件

void show(const char *pillow,char data){
	int i;
	for(i=0;i<size;i++){
		printf("%c ",vect[i]);	
	}
	printf("%s [%c] %lu\n",pillow,data,pthread_self());
}

//生产者
void *producer(void *arg){
	while(true){//一直在生产
		pthread_mutex_lock(&lock);
		//if(size >= MAX_SIZE){//仓库满了
		while(size >= MAX_SIZE){//仓库满了
			pthread_cond_wait(&notfull,&lock);//要等待仓库不满的条件,同时释放锁	当notfull条件变量满足时 会被唤醒 同时会去获得锁
		}
		char data = rand()%26+'A';
		show("<---",data);
		vect[size++] = data;
		//pthread_cond_signal(&notempty);
		pthread_cond_broadcast(&notempty);
		pthread_mutex_unlock(&lock);
		usleep(rand()%100*1000);
	}
	return NULL;
}
//生产了一个数据   同时唤醒所有的消费者 3
//消费者
void *customer(void *arg){
	while(true){//一直在消费
		pthread_mutex_lock(&lock);
		//if(size == 0){//仓库为空
		while(size == 0){//仓库为空
			pthread_cond_wait(&notempty,&lock);
		}
		char data = vect[--size];
		show("--->",data);
		//pthread_cond_signal(&notfull);
		pthread_cond_broadcast(&notfull);
		pthread_mutex_unlock(&lock);
		usleep(rand()%100*1000);
	}
	return NULL;
}


int main(){
	srand(time(NULL));
	int ret = 0;
	//初始化
	ret = pthread_mutex_init(&lock,NULL);
	ret = pthread_cond_init(&notfull,NULL);
	ret = pthread_cond_init(&notempty,NULL);

	pthread_t ids[6];
	int i;
	for(i=0;i<3;i++)
		pthread_create(&ids[i],NULL,producer,NULL);
	
	for(;i<6;i++)
		pthread_create(&ids[i],NULL,customer,NULL);

	for(i=0;i<6;i++)
		pthread_join(ids[i],NULL);
	//销毁
	pthread_mutex_destroy(&lock);
	pthread_cond_destroy(&notfull);
	pthread_cond_destroy(&notempty);

	return 0;	
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-03 11:43:10  更:2021-09-03 11:45:38 
 
开发: 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年12日历 -2024/12/27 21:27:42-

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