线程同步(互斥锁、读写锁、条件变量、信号量)

线程同步防止数据混乱,关键在于同步机制。互斥锁实现资源独占,读写锁实现写独占、读共享,条件变量与互斥锁配合减少不必要的竞争,信号量则允许多个线程访问。文章详细介绍了这些概念及相关函数,包括互斥锁的初始化、加锁、解锁,读写锁的特性及其函数,条件变量的使用,以及信号量的初始化和操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

线程同步:

线程同步指一个线程发出某一功能调用时,在没有得到结果之前,该调用不返回。同时其它线程为保证数据一致性,不能调用该功能。保证了数据的一致性。举个简单的例子就是,当一个线程将全局变量var=100加上10,另外一个线程时将var乘以2,这样最后得出的结果因为cpu不同的调度策略导致不同的结果,可能是220也可能是210还可能是110或者200,220和210可以理解,无非就是一个先操作一个后操作,但是110和200呢,这是因为两个线程读取到var的值为100时,都进行了操作,导致另外一个线程运行出来的结果被覆盖了,为了得到我们想要的结果,不让数据出现混乱,就需要进行同步。

造成数据混乱的原因:

1.资源共享
2.随机调度
3.缺乏同步机制

前两点我们无法改变,而第三点就是解决数据混乱的关键。这里就引入了锁机制。

互斥锁
相关概念:

Linux提供互斥锁mutex(又称互斥量)。每个线程在对资源进行操作前都尝试先加锁,成功加锁了之后才能操作该资源,操作结束后就解锁。在同一时间,锁只有一把,如果线程A加锁正在访问资源,这时B尝试加锁,就会阻塞。但是互斥锁有个特点,就是不加锁也可以访问数据,比如之前的线程A加锁了正在访问资源,这时B不加锁也可以直接访问数据。所以互斥锁实质上是操作系统提供的一把”建议锁”,没有进行强制限定必须有锁才能访问。

相关函数:

初始化互斥锁:
函数原型:int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
返回值:成功返回0,失败返回错误号
参数:mutex:传出参数,代表互斥锁;attr:传入参数,代表互斥锁属性,使用默认属性(线程间共享)传NULL。pthread_mutex_t变量类型是一个结构体,可以简单理解成整数,只有1或者0两个取值,初始值为0。
销毁互斥锁:
函数原型:int pthread_mutex_destroy(pthread_mutex_t *mutex);
返回值:成功返回0,失败返回错误号
参数:mutex:传出参数,要销毁的互斥锁。
加锁:
函数原型:int pthread_mutex_lock(pthread_mutex_t *mutex);
返回值:成功返回0,失败返回错误号。
参数:mutex:传出参数,要加锁的互斥锁。
可理解为将mutex–。如果已有线程进行了加锁,那么就会阻塞等待,直到持有该互斥锁的其它进程解锁为止。
尝试加锁:
函数原型:int pthread_mutex_trylock(pthread_mutex_t *mutex);
返回值:成功返回0,失败返回错误号。
参数:mutex:传出参数,要尝试加锁的互斥锁。如果已有线程进行了加锁,不会阻塞,直接返回错误号。
解锁:
函数原型:int pthread_mutex_unlock(pthread_mutex_t *mutex);
返回值:成功返回0,失败返回错误号
参数:mutex:传出参数,要解锁的互斥锁。
可理解为mutex++。当解锁成功时,该函数会把阻塞在该锁上的所有线程全部唤醒,之后哪个线程抢到锁继续执行,就是调度优先级的问题了,默认是先阻塞的先唤醒。

继续引用开头那个例子,引用互斥锁的机制就可以避免200和110这样的答案出现。

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <pthread.h>

int var = 100;
pthread_mutex_t mutex;  //定义互斥锁变量mutex
void *test1(void *arg)
{
    pthread_mutex_lock(&mutex);     //加锁
    var += 10;
    pthread_mutex_unlock(&mutex);   //解锁
    return NULL;
}
void *test2(void *arg)
{
    pthread_mutex_lock(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值