目录
前言:为什么要引入互斥锁?
在多线程编程中,我们常遇到的问题是当多个线程同时访问共享数据时可能会产生冲突。比如:存在多个线程同时要对一个全局变量进行加一操作,我们知道加一操作需要以下三条指令完成:
从内存中将变量值读取到寄存器中;
将寄存器中的值加一操作;
将寄存器中的值写回内存中;
下图所示:假设有两个线程同时执行以上三条指令,则可能会出现以下情况,线程A
将变量值(a=5
)读取到寄存器中,并将寄存器中的值加一(a=6
),而此时线程B
正好将变量的值读取到寄存器中(a=5
)。当线程A
将寄存器中的值写入内存后,该变量的值完成了加一操作(a=6
),而随后线程B
也将加一的值写回内存中(a=6
),那么最终变量的值只是完成的加一操作,而不是加一再加一。
———————————————————————————————————————————
一、互斥锁的相关函数
pthread_mutex_init 初始化一个互斥锁 pthread_mutex_destroy 注销一个互斥锁 pthread_mutex_lock 加锁成功,如果不成功则阻塞等待 pthread_mutex_unlock 解锁操作 pthread_mutex_trylock 测试加锁,如果不成功则立刻返回
二、实现一个简单的互斥锁程序
(1)锁的初始化
锁的初始化有两种
1:静态赋值法
PTHREAD_MUTEX_INITIALIZER: (普通锁)当一个线程加锁后,其余请求锁的线程形成等待队列,解锁后按照优先级获取锁;
PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: (嵌套锁)允许一个线程对同一个锁进行多次加锁操作,并通过多次解锁来释放锁;
PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: (检错锁)在同一个线程请求同一个锁的情况下,返回EDEADLK,否则执行的动作与普通锁相同;
锁的初始化赋值:
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER
2:函数赋值法
使用pthread_mutex_init函数进行赋值,具体使用如下:
pthread_mutex_init(a,b) 该函数接受两个参数a,b a:互斥锁变量 b:互斥锁属性,若为NULL则是默认属性
PTHREAD_MUTEX_TIMED_NP 普通锁: 当一个线程加锁后,其余请求锁的线程形成等待队列,解锁后按照优先级获取锁 PTHREAD_MUTEX_RECURSIVE_NP 嵌套锁: 允许一个线程对同一个锁进行多次加锁操作,并通过多次解锁来释放锁 PTHREAD_MUTEX_ERRORCHECK_NP 检错锁: 在同一个线程请求同一个锁的情况下,返回 EDEADLK
,否则执行的动作与普通锁相同
示例:
pthread_mutex_t mutex; pthread_mutex_init(&mutex,PTHREAD_MUTEX_TIMED_NP);
(2)上锁和解锁
pthread_mutex_lock(加锁操作的锁变量) pthread_mutex_unlock(解锁操作的锁变量) 两个函数调用成功后返回值都是0
示例:
#include<stdio.h> #include<pthread.h> #include<stdlib.h> //仅仅只是部分代码,未写程序入口 pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER; void *p(void* data) { //上锁 pthread_mutex_lock(&mutex); //解锁 pthread_mutex_unlock(&mutex); }
(3)锁的注销
当一个互斥锁使用完毕后必须要进行清除,Linux提供了pthread_mutex_destroy函数
pthread_mutex_destrot(&a) 接受一个参数a a:锁变量 调用成功返回值是0
示例:
#include<stdio.h> #include<pthread.h> //伪代码 pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER; void *p(void* data) { //上锁 pthread_mutex_lock(&mutex); //解锁 pthread_mutex_unlock(&mutex); } int main() { //锁的注销 pthread_mutex_destroy(&mutex); }
三、编写一个简单的互斥锁程序
#include<stdio.h> #include<stdlib.h> #include<pthread.h> int n=1; pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER; void *p(void *data) { //上锁 pthread_mutex_lock(&mutex); n++; //解锁 pthread_mutex_unlock(&mutex); } int main() { pthread_t t1,t2; pthread_create(&t1,NULL,p,NULL); pthread_join(t1,NULL); pthread_create(&t2,NULL,p,NULL); pthread_join(t2,NULL); printf("n=%d\n",n); //注销锁 pthread_mutex_destroy(&mutex); return 0; }