线程间的互斥与同步

举报
似曾相识 发表于 2022/01/14 23:24:32 2022/01/14
【摘要】 线程间互斥:对于临界资源区,同一时刻只能由一个线程访问。线程间同步:有些线程需要有次序的运行,这时候就要用到进程间同步。

生产者消费者问题(用于理解线程间互斥与同步的典型事例)


线程间互斥:对于临界资源区,同一时刻只能由一个线程访问。相当于仓库,生产好的产品入库时,就不能从仓库中取东西;从仓库中取东西时,就不能将生产好的产品入库。
线程间同步:有些线程需要有次序的运行,这时候就要用到进程间同步。相当于仓库,只有在仓库中的产品数量大于0时,从仓库中取产品的操作才能进行;只有在仓库中的产品数量小于总数时,新产品入库的操作才能进行。

线程间互斥:互斥锁
线程间同步:信号量

/*************************************************************************
	> File Name: pv.c
	> Author: LiYongjun
	> Mail: 1160606604@qq.com 
	> Created Time: Mon 25 Feb 2019 02:10:47 PM CST
 ************************************************************************/

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

pthread_mutex_t mutex;	//互斥锁,用于互斥,保护临界资源,同一时刻只能有一人操作仓库
sem_t empty, full;		//信号量,用于同步,生产者消费者问题
int sum;

void *t1_fun(void *arg)
{
	while(1)
	{
		sem_wait(&full);	//full - 1
		pthread_mutex_lock(&mutex);		//上锁
		sum--;
		printf("thread 1, sum = %d\n", sum);
		sleep(1);
		pthread_mutex_unlock(&mutex);	//解锁
		sem_post(&empty);	//wait + 1
	}
}

void *t2_fun(void *arg)
{
	while(1)
	{
		sem_wait(&empty);	//empty - 1
		pthread_mutex_lock(&mutex);		//上锁
		sum++;
		printf("thread 2, sum = %d\n", sum);
		sleep(3);
		pthread_mutex_unlock(&mutex);	//解锁
		sem_post(&full);	//full + 1
	}
}

int main(int argc, char *argv[])
{
	pthread_mutex_init(&mutex, NULL);	//初始化互斥量
	sem_init(&empty, 0, 5);				//初始化信号量
	sem_init(&full, 0, 0);
	pthread_t t1, t2;
	pthread_create(&t1, NULL, t1_fun, NULL);
	pthread_create(&t2, NULL, t2_fun, NULL);
	while(1)
	{
		sleep(10);
	}
}

执行结果

[root@VM_0_14_centos test]# gcc pv.c -lpthread
[root@VM_0_14_centos test]# ./a.out 
thread 2, sum = 1
thread 2, sum = 2
thread 2, sum = 3
thread 2, sum = 4
thread 2, sum = 5
thread 1, sum = 4
thread 1, sum = 3
thread 1, sum = 2
thread 1, sum = 1
thread 1, sum = 0
thread 2, sum = 1
thread 2, sum = 2
thread 2, sum = 3
thread 2, sum = 4
thread 2, sum = 5

可以看到,仓库中产品的数量永远介于0~5之间(5为仓库最大容量)。

注解:
1.互斥锁
pthread_mutex_init()
函数原型:int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
pthread_mutex_init()函数是以动态方式创建互斥锁的,参数attr指定了新建互斥锁的属性。如果参数attr为空,则使用默认的互斥锁属性,默认属性为快速互斥锁 。

pthread_mutex_lock()
当pthread_mutex_lock()返回时,该互斥锁已被锁定。线程调用该函数让互斥锁上锁,如果该互斥锁已被另一个线程锁定和拥有,则调用该线程将阻塞,直到该互斥锁变为可用为止。

pthread_mutex_unlock()
pthread_mutex_unlock()可释放mutex引用的互斥锁对象。

2.信号量
sem_init()
原型:int sem_init(sem_t *sem, int pshared, unsigned int value);
sem :指向信号量对象
pshared : 指明信号量的类型。不为0时此信号量在进程间共享,否则只能为当前进程的所有线程共享。
value : 指定信号量值的大小

sem_wait()
sem_wait是一个函数,也是一个原子操作,它的作用是从信号量的值减去一个“1”,但它永远会先等待该信号量为一个非零值才开始做减法。也就是说,如果你对一个值为2的信号量调用sem_wait(),线程将会继续执行,将信号量的值将减到1。
如果对一个值为0的信号量调用sem_wait(),这个函数就会原地等待直到有其它线程增加了这个值使它不再是0为止。

sem_post()
sem_post是给信号量的值加上一个“1”,它是一个“原子操作”---即同时对同一个信号量做加“1”操作的两个线程是不会冲突的;而同 时对同一个文件进行读和写操作的两个程序就有可能会引起冲突。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。