互斥锁是我们用来解决线程同步的一种常用方法,它的头文件在#include<pthread>中
1.互斥锁的创建
pthread_mutex_t mutex;
2.创建完成之后需要初始化
pthread_mutex_init(
pthread_mutex_t* mutex;
const pthread_mutexattr_t attr; //一般传NULL
);
3.用完之后需要销毁锁
pthread_mutex_destroy(pthread_mutex_t *mutex);
4.加锁
pthread_mutex_lock(pthread_mutex_t* mutex);
mutex没有被上锁,当前线程会将这把锁锁上,如果被锁上了,当前线程被阻塞;锁被打开之后,线程解除阻塞
5.尝试加锁
pthread_mutex_trylock(pthread_mutex_t*mutex)
没有锁上:当前线程会给这把锁加锁;如果锁上了,不会阻塞,也可以执行其他操作
if(pthread_mutex_trylock(&mutex) == 0)
{
//尝试加锁,并且成功,访问共享资源
}
else
{
//错误处理,或者等一会,再次尝试加锁
}
6.解锁
pthread_mutex_unlock(pthread_mutex_t *mutex);
下面我们用互斥锁写一个例子,用两个线程数数,每一个线程数10000,不加锁是数不到两万的。只有加锁之后才可以到两万,(虚拟机必须是双核的)
1 #include<stdio.h>
2 #include<pthread.h>
3 #include<string.h>
4 #include<stdlib.h>
5 #include<unistd.h>
6
7
8 #define MAX 10000
9 //数数需要创建一个全局变量
10 int num;
11 //创建一个全局变量的锁
12 pthread_mutex_t mutex;
13
14 void *fun1(void * arg)
15 {
16 int i = 0;
17 for(;i < MAX;i++)
18 {
19 pthread_mutex_lock(&mutex);
20 int tmp = num;
21 tmp++;
22 num = tmp;
23
24 printf("first pthread = %lu,num = %d\n",pthread_self,num);
25 pthread_mutex_unlock(&mutex);
26
27 usleep(10);
28 }
29
30 return NULL;
31 }
32
33 void *fun2(void *arg)
34 {
35 int i = 0;
36 for(;i < MAX;i++)
37 {
38 pthread_mutex_lock(&mutex);
39 int tmp = num;
40 tmp++;
41 num = tmp;;
42
43 printf("scend pthread = %lu,num = %d\n",pthread_self(),num);
44 pthread_mutex_unlock(&mutex);
45
46 usleep(10);
47 }
48
49 return NULL;
50 }
51 int main()
52 {
53 //定义两个线程ID
54 pthread_t p1,p2;
55
56 //初始化互斥锁
57 pthread_mutex_init(&mutex,NULL);
58 //创建两个线程
59 pthread_create(&p1,NULL,fun1,NULL);
60 pthread_create(&p2,NULL,fun2,NULL);
61
62
63 //等待线程结束,获取线程的退出状态
64 pthread_join(p1,NULL);
65 pthread_join(p2,NULL);
66
67 return 0;
68 }
没加锁时,两个线程访问这个全局变量num是并行的,但是在在加锁之后就成串行的了,之后一个用完之后,另一个才能用。相当于满了很多,但是却实现了线程的同步。