参考学习资料:进程线程互斥与同步
1. 互斥锁(互斥量)
1.1 变量类型:互斥锁类型
创建一把锁:
//变量类型 变量名
pthread_mutex_t mutex
1.2 互斥锁的特点
多个线程访问共享数据时是串行的,避免数据混乱。
1.3 互斥锁缺点
效率低(由于所有的并行都转串行,所以效率比较低)。
1.4 互斥锁使用步骤
- 创建互斥锁:
pthread_mutex_t mutex;
-
初始化这把锁:
pthread_mutex_init(&mutex,NULL);
(可以理解为此时mutex=1,有一把锁可以用)
-
寻找共享资源:操作共享资源的代码之前加锁
pthread_mutex_lock(&mutex);
被lock和unlock锁住的代码段一般称为临界区,在避免资源冲突的前提下,临界区越小越好。(lock之后,可以理解为mutex--,即mutex=0,此时无可用锁)
-
解锁:
pthread_mutex_unlock(&mutex)
(解锁之后,mutex=1,有一把锁可以使用)
1.5 互斥锁相关函数
- 初始化互斥锁
pthread_mutex_init( pthread_mutex_t* mutex, //互斥锁锁对象 const pthread_mutexattr_t* sttr //初始化参数,一般默认NULL );
-
销毁互斥锁
pthread_mutex_destroy(pthread_mutex_t *mutex);
-
加锁
pthread_mutex_lock(pthread_mutex_t* mutex);
加锁时,如果锁没有被锁上,当前线程会将这把锁锁上;如果锁被锁上了,当前线程阻塞,锁被打开之后,线程解除阻塞。
-
尝试加锁,失败返回,不阻塞
pthread_mutex_trylock(pthread_mutex_t *mutex);
锁没有锁上时,当前线程给这把锁加锁;锁上了,不会阻塞,而是直接返回。
if(pthread_mutex_trylock(&mutex)==0) { //尝试加锁,并且成功了 //访问共享资源 } else{ //错误处理 //或者稍等一会,再次尝试加锁 }
-
解锁
pthread_mutex_unlock(pthread_mutex_t* mutex);
如果使用互斥锁,所有访问相同共享资源的线程都需要加锁和解锁。
2. 代码示例(C语言)
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pthread.h>
#include <string.h>
#define MAX 10000
int number;
//创建一把互斥锁
pthread_mutex_t mutex;
//线程处理函数 A
void* funcA_num(void* arg){
int i=0;
for(i=0;i<MAX;i++){
//访问全局变量之前加锁
//如果mutex被锁上了,线程阻塞在这一行
pthread_mutex_lock(&mutex);
int cur=number;
cur++;
number=cur;
printf("Thread A, id = %lu, number = %d\n",pthread_self(),number);
//操作完成之后,解锁
pthread_mutex_unlock(&mutex);
usleep(10);
}
return NULL;
}
//线程处理函数 B
void* funcB_num(void* arg){
int i=0;
for(;i<MAX;i++){
//访问全局变量之前加锁
//如果mutex被锁上了,线程阻塞在这一行
pthread_mutex_lock(&mutex);
int cur=number;
cur++;
number=cur;
printf("Thread B, id = %lu, number = %d\n",pthread_self(),number);
//操作完成之后,解锁
pthread_mutex_unlock(&mutex);
usleep(10);
}
return NULL;
}
int main(int argc, const char* argv[]){
pthread_t p1,p2;
//对互斥锁做初始化
pthread_mutex_init(&mutex,NULL);
//创建两个线程
pthread_create(&p1,NULL,funcA_num,NULL);
pthread_create(&p2,NULL,funcB_num,NULL);
//阻塞回收线程的资源
pthread_join(p1,NULL);
pthread_join(p2,NULL);
//释放互斥对象
pthread_mutex_destroy(&mutex);
return 0;
}