mutex锁

互斥锁

特征

在多个线程或者进程间保护一块共享的数据块,保证同一时间只有一个线程或者进程对这块数据进行操作,其实申请操作的进程或者线程被阻塞,等到当前操作完成之后释放mutex,所有等待的进程或者线程竞争这个mutex,只用一个成功,其它的继续阻塞。

数据结构

mutex的数据结构是pthread_mutex_t

mutex属性的数据结构是pthread_mutexattr_t

互斥锁用法

int pthread_mutex_init(const pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict  attr);

int pthread_mutex_trylock(pthread_mutex_t *mutex);

int pthread_mutex_lock(pthread_mutex_t *mutex);

int pthread_mutex_unlock(pthread_mutex_t *mutex);

int pthread_mutex_destroy(pthread_mutex_t *mutex);

初始化的时候需要指定一个attr值,也可以指定为NULL,初始化的时候使用默认值。

虽然mutex是针对线程开发的,但是它也可以在进程间使用,要使用这个功能就不能再使用默认值了,必须亲自设定attr的值。

互斥锁的属性用法

int pthread_mutexattr_init(const pthread_mutexattr_t * attr);

int pthread_mutexattr_getpshared(pthread_mutexattr_t *restrict attr,int *restrict pshared);

int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr,int pshared);

pshared的可选值有两个,一个是PTHREAD_PROCESS_PRIVATE 另一个是PTHREAD_PROCESS_SHARED。PTHREAD_PROCESS_PRIVATE是默认值,这种情况下只能在线程间使用,PTHREAD_PROCESS_SHARED就是进程间需要使用互斥变量保护数据的时候使用,这两个参数的区别直接导致了实现方法的不一样,PTHREAD_PROCESS_PRIVATE的效率要高不少。

int pthread_mutexattr_getrobust(pthread_mutexattr_t *restrict attr,int *restrict robust);

int pthread_mutexattr_setrobust(pthread_mutexattr_t *attr,int robust);

在属性被设置成为PTHREAD_PROCESS_SHARED使用在进程间的时候会有一种线程间不会出现的问题,就是一个持有互斥变量的进程退出了,而且退出的时候没有释放互斥变量,这个时候就要有一个选择,是不管它还是从错误中恢复过来。这两个选择也就是robust的两个取值PTHREAD_MUTEX_STALLED和PTHREAD_MUTEX_ROBUST,stalled是默认值,就是啥也不做。如果设置成robust,等待互斥变量的线程会获取到mutex,并从pthread_mutex_lock返回,但是返回值是EOWNERDEAD,不是正常的返回值0,这种情况下获取到的mutex就要注意啦,在pthread_mutex_unlock之前要执行一个 pthread_mutex_consistent,如果不执行会怎么样呢,就算不执行unlock也会成功就是苦了将到申请互斥锁的线程了,因为他们不能成功的lock,取面代之的是返回一个错误ENOTRECOVERABLE。

int pthread_mutex_consistent(pthread_mutex_t *mutex);

它的意义就是告诉系统这个互斥锁虽然经历了出错的情况,但是它保护的数据状态没有问题,可以继续执行要去。所以在调用pthread_mutex_consistent的时候要进行检查,它要保护的数据到底有没有问题,有没有乱,别不管乱没有乱直接调用pthread_mutex_consistent,那样子程序产生的结果就不可预料了。

int pthread_mutexattr_gettype(const pthread_mutexattr_t *restrict attr,int *restrict type);

int pthread_mutexattr_settype(pthread_mutexattr_t *attr,int type);

type 的值决定互斥锁如何互斥,有四个可选值,

PTHREAD_MUTEX_NORMAL

PTHREAD_MUTEX_ERRORCHECK

PTHREAD_MUTEX_RECURSIVE

PTHREAD_MUTEX_DEFAULT

一般default被映射成normal,不进行错误检查,连续锁两次就会死锁了,不拥有锁而执行解锁和已经解锁再次解锁是一个意思,导致的结构就是undefined,这可是出错的节奏。

errorcheck就不一样了,非合法的操作会返回错误,这点比较好啊。recursive是指一个线程可以多次lock,不过你lock多少次要unlock多少次,其它情况表现和errorcheck一样。

在 C++ 中,std::mutex 是一种用于线程同步的互斥量。当一个线程正在访问某个共享资源时,可以使用 std::mutex 对这个资源进行加,以确保其他线程在此期间无法访问该资源,从而避免数据竞争的问题。 使用 std::mutex 一般需要以下步骤: 1. 定义一个 std::mutex 对象; 2. 在需要保护的代码块前调用 std::mutex 的 lock() 方法,以住互斥量; 3. 在保护的代码块执行完毕后,调用 std::mutex 的 unlock() 方法,以释放互斥量。 例如,下面是一个简单的示例代码,展示了如何使用 std::mutex 来保护一个共享变量: ```c++ #include <iostream> #include <thread> #include <mutex> std::mutex mtx; int shared_var = 0; void increment_shared_var(int id) { for (int i = 0; i < 100000; ++i) { mtx.lock(); ++shared_var; mtx.unlock(); } } int main() { std::thread t1(increment_shared_var, 1); std::thread t2(increment_shared_var, 2); t1.join(); t2.join(); std::cout << "shared_var = " << shared_var << std::endl; return 0; } ``` 在这个例子中,我们定义了一个全局的 std::mutex 对象 mtx 和一个共享变量 shared_var,然后启动两个线程来分别对 shared_var 进行 100000 次自增操作。在每次自增操作前,我们都使用 mtx.lock() 方法来住互斥量,以确保只有一个线程能够访问共享变量。在自增操作完成后,我们再调用 mtx.unlock() 方法来释放互斥量。 运行这个程序,你会发现最终输出的 shared_var 值为 200000,这说明两个线程对共享变量进行了正确的并发更新,并且互斥量起到了保护作用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值