互斥锁同步互斥

为了保护共享资源,使我们线程可以单独使用某个共享资源,使用之前先上锁,当其他进程要使用的时候,就需要等待到这个线程用完之后,再开锁。

  1. 声明互斥锁:pthread_mutex_t m;
  2. 初始化互斥锁:int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);第一个参数:就是前面声明的锁,因为这个参数需要传递的是一个锁的指针,所以需要有一个取地址符。第二个参数:是这个锁的属性,我们让它是默认的属性,这里设置为NULL,返回值:成功返回0, 失败返回-1。
  3. 上锁:锁住某个资源int pthread_mutex_lock(pthread_mutex_t *mutex); 这个函数是阻塞型。int pthread_mutex_trylock(pthread_mutex_t *mutex); 这个是非阻塞型的。返回值:成功返回0,失败返回-1.
  4. 解锁:int pthread_mutex_unlock(pthread_mutex_t *mutex); 返回值:成功返回0,失败返回-1.
  5. 销毁互斥锁:int pthread_mutex_destroy(pthread_mutex_t *mutex); 返回值:成功返回0, 失败返回-1。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>

pthread_mutex_t mutex; //定义互斥量
char* buf[5]; //字符指针数组 全局变量
int pos; //用于指定上面数组的下标

void* task(void* p)
{
//使用互斥量进行加锁
pthread_mutex_lock(&mutex);

buf[pos] = (char*)p;
sleep(1);
pos++;

//使用互斥量进行解锁
pthread_mutex_unlock(&mutex);
}


void* task2(void* p)
{
//使用互斥量进行加锁
pthread_mutex_lock(&mutex);

buf[pos] = (char*)p;
sleep(1);
pos++;

//使用互斥量进行解锁
pthread_mutex_unlock(&mutex);
}


int main(void)
{
//初始化互斥量, 默认属性
pthread_mutex_init(&mutex, NULL);

//启动一个线程 向数组中存储内容
pthread_t tid, tid2;
pthread_create(&tid, NULL, task, (void*)"贾鹏城\n");
pthread_create(&tid2, NULL, task2, (void*)"OperatingSystem\n");

//主线程进程等待,并且打印最终的结果
pthread_join(tid, NULL);
pthread_join(tid2, NULL);

pthread_mutex_destroy(&mutex);

int i = 0;
printf("字符指针数组中的内容是:\n");
for (i = 0; i < pos; ++i) {
printf("%s ", buf[i]);
}

}

互斥锁同步互斥

读写锁同步互斥

读写锁:

如果某线程申请了读锁,其它线程可以再申请读锁,但不能申请写锁;如果某线程申请了写锁,其它线程不能申请读锁,也不能申请写锁。

读写锁适合于对资源的读次数比写次数多得多的情况。

实例,两个读线程两个写线程,写互斥地对字符数组操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>


char cBuf[30];
pthread_rwlock_t rwlock; //读写锁


//write线程函数,负责往buf里面加字符
void *taskWrite(void *p)
{
while (1)
{
pthread_rwlock_wrlock(&rwlock);
if (pos < 29)
{
cBuf[pos] = 'A';
pos++;
printf("Write cBuf is: %s \n", cBuf);
}
pthread_rwlock_unlock(&rwlock);
sleep(1);
}
}


//write线程函数,负责从buf里面删除字符
void *taskWriteDel(void *p)
{
while (1)
{
pthread_rwlock_wrlock(&rwlock);
if (pos > 0)
{
cBuf[pos-1] = 0;
pos--;
printf("WriteDel cBuf is: %s \n", cBuf);
}
pthread_rwlock_unlock(&rwlock);
sleep(1);
}
}


void *taskRead(void *p)
{
while (1)
{
pthread_rwlock_rdlock(&rwlock);
if (pos > 0)
{
printf("read cBuf is: %s \n", cBuf);
}
pthread_rwlock_unlock(&rwlock);
}
}


void *taskRead2(void *p)
{
while (1)
{
pthread_rwlock_rdlock(&rwlock);
if (pos > 0)
{
printf("read2 cBuf is: %s \n", cBuf);
}
pthread_rwlock_unlock(&rwlock);
}
}


int main(void)
{
pthread_t ptd1, ptd2, ptd3, ptd4;
pos = 0;


pthread_rwlock_init(&rwlock, NULL);//初始化一个读写锁


//创建线程
pthread_create(&ptd1, NULL, taskWrite, NULL);
pthread_create(&ptd2, NULL, taskWriteDel, NULL);
pthread_create(&ptd3, NULL, taskRead, NULL);
pthread_create(&ptd4, NULL, taskRead2, NULL);


//等待线程结束,回收其资源
pthread_join(ptd1, NULL);
pthread_join(ptd2, NULL);
pthread_join(ptd3, NULL);
pthread_join(ptd4, NULL);


pthread_rwlock_destroy(&rwlock);//销毁读写锁
}

读写锁

自旋锁

自旋锁与互斥量功能一样,唯一一点不同的就是互斥量阻塞后休眠让出cpu,而自旋锁阻塞后不会让出cpu,会一直忙等待,直到得到锁。

接口上就是把互斥锁的mutex改成spin。

实例 两个线程各自数数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>


pthread_spinlock_t spinMutex;


void *task5(void *p)
{
int cur = 0;
while (1)
{
//3.使用互斥量进行加锁
pthread_spin_lock(&spinMutex);
printf("task5 %d\n", cur);
cur++;
sleep(0);
//4.使用互斥量进行解锁
pthread_spin_unlock(&spinMutex);
}
}
void *task6(void *p)
{
int cur = 0;
while (1)
{
//3.使用互斥量进行加锁
pthread_spin_lock(&spinMutex);
printf("task6 %d\n", cur);
cur++;
sleep(0);
//4.使用互斥量进行解锁
pthread_spin_unlock(&spinMutex);
}
}


int main(void)
{
pthread_spin_init(&spinMutex, NULL);


pthread_t tid3, tid4;
pthread_create(&tid3, NULL, task5, (void *)"zhangfei");
pthread_create(&tid4, NULL, task6, (void *)"zhangfei");


pthread_join(tid3, NULL);
pthread_join(tid4, NULL);


pthread_spin_destroy(&spinMutex);
}