线程同步(信号量/互斥锁/条件变量)

线程同步:

同步的概念与进程同步的概念一致,让多个线程按照顺序协同执行。为什么线程需要线程同步呢?因为线程很多资源都是共享的,比如全局数据,内存,文件,数据库等等。当多个线程同时读写同一份共享资源的时候,可能会引起冲突。这时候,我们需要引入线程“同步”机制,即各位线程之间要有个先来后到,不能一窝蜂挤上去抢作一团。(同步大多都互斥)
还有一点,因为我们在一个线程中有时候进行的操作并不一定是原子操作,那么如果多个线程同时执行,就有可能会发生线程不安全,进行同步控制后,就可以实现线程安全。

线程同步的机制:

信号量(对临界资源的计数器)

同进程同步相似,线程这里也可以使用信号量来进行同步,但是与进程的还是有些不同

//信号量的创建与初始化,都在一个函数里,同进程的信号量不同
#include<semaphore.h>
int sem_init(sem_t *semid,int shared,unsigned int val);
                        //失败返回-1,成功返回0

semid:标识操作的信号量,一般是一个全局变量(共享)

shared:控制信号量的类型,指定此信号量是否在进程间共享,如果是0则是当前进程局部的信号量,否则这个信号量可以在多个进程中共享,但是Linux还不支持这种共享,所以一般默认值我们会给0。

val:设置信号量的初始值 

//控制信号量的两个函数
#include<semaphore.h>
int sem_wait(sem_t *semid);   //相当于p操作,给参数sem指定的信号量值减1,会阻塞
int sem_post(sem_t *Semid);   //相当于v操作,给参数sem指定的信号量值加1
        //这几个函数都在线程库中封装好了,不用像进程那样自己封装,方便用户调用

在这里说明一点,sem_wait调用的时候,如果信号量不为0则直接给信号量减1继续执行,不会阻塞的,但是如果信号量等于0,调用此函数就会阻塞,等待着其他线程的运行,直到信号零不为0可被调度。但是我们还有一个函数,与sem_wait行使作用一致但是不会阻塞。

#include<semaphore.h>
int sem_trywait(sem_t *semid);
            //相当于p操作,给信号零减1,但是不会阻塞

对于信号量的销毁,我们线程库也为用户封装好了,用户可以直接调用

#include<semaphore.h>
int sem_destroy(sem_t *semid);  //销毁信号量

信号量同步实例:

//两个线程交替打印
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<pthread.h>
#include<semaphore.h>

sem_t sem;  //信号量,设为全局量,使得线程共享
void *fun(void *arg)
{
	printf("fun thread start\n");
	int i=0;
	for(;i<8;i++)
	{
		sem_wait(&sem);
		printf("fun pthread running\n");
		sleep(1);
		sem_post(&sem);
	}
	printf("fun pthread end\n");
	pthread_exit(NULL);
}
void destory()
{
	printf("destory\n");
	sem_destroy(&sem);
}
int main()
{
	atexit(destory);  //注册函数,进程结束会调用它所注册的函数
	int n=sem_init(&sem,0,1);
	pthread_t id;
	int res=pthread_create(&id,NULL,fun,NULL);
	assert(res==0);
	printf("main pthread start\n");

	int i=0;
	for(;i<10;i++)
	{
		sem_wait(&sem);
		printf("main pthrea
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值