互斥锁与条件变量

互斥锁与条件变量

1. 互斥锁(Mutex)

1.1 互斥锁的概念

  • 互斥锁 是一种用于保护共享资源的同步原语,确保同一时间只有一个线程可以进入临界区。
  • 使用互斥锁可以防止多个线程并发访问共享数据导致的数据不一致。

1.2 互斥锁的基本操作

1.2.1 初始化互斥锁

在使用互斥锁之前,需先进行初始化。可以使用 pthread_mutex_init 函数:

1
2
3
4
#include <pthread.h>

pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);

1.2.2 加锁与解锁

线程在进入临界区之前需要加锁,离开临界区后需要解锁:

1
2
3
pthread_mutex_lock(&mutex); // 加锁
// 临界区代码
pthread_mutex_unlock(&mutex); // 解锁

1.2.3 销毁互斥锁

当不再需要互斥锁时,使用 pthread_mutex_destroy 进行销毁:

1
pthread_mutex_destroy(&mutex);

1.3 互斥锁使用示例

以下是一个简单的示例,说明如何使用互斥锁来保护共享变量:

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
#include <stdio.h>
#include <pthread.h>

#define NUM_THREADS 5

int counter = 0; // 共享资源
pthread_mutex_t mutex;

void* increment(void* arg) {
for (int i = 0; i < 10000; i++) {
pthread_mutex_lock(&mutex);
counter++; // 访问共享资源
pthread_mutex_unlock(&mutex);
}
return NULL;
}

int main() {
pthread_t threads[NUM_THREADS];
pthread_mutex_init(&mutex, NULL);

for (int i = 0; i < NUM_THREADS; i++) {
pthread_create(&threads[i], NULL, increment, NULL);
}
for (int i = 0; i < NUM_THREADS; i++) {
pthread_join(threads[i], NULL);
}

printf("Final counter value: %d\n", counter);
pthread_mutex_destroy(&mutex);
return 0;
}

2. 条件变量(Condition Variables)

2.1 条件变量的概念

  • 条件变量是用于线程间同步的一种机制,允许线程在某个条件发生变化时被唤醒。
  • 常与互斥锁一起使用,以确保在修改共享变量时有适当的保护。

2.2 条件变量的基本操作

2.2.1 初始化条件变量

使用 pthread_cond_init() 来初始化条件变量:

1
2
pthread_cond_t cond;
pthread_cond_init(&cond, NULL);

2.2.2 等待条件变量

线程在条件没有满足时,可以调用 pthread_cond_wait()来挂起自己,并释放互斥锁。该函数的原型为:

1
pthread_cond_wait(&cond, &mutex);

2.2.3 发送信号(广播)

当条件改变时,使用 pthread_cond_signal()pthread_cond_broadcast() 来唤醒一个或所有等待此条件变量的线程:

1
2
pthread_cond_signal(&cond); // 唤醒一个线程
pthread_cond_broadcast(&cond); // 唤醒所有线程

2.2.4 销毁条件变量

当不再需要条件变量时,使用 pthread_cond_destroy()

1
pthread_cond_destroy(&cond);

2.3 条件变量使用示例

以下是使用条件变量的示例,它展示了生产者-消费者问题的基本实现:

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
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>

#define BUFFER_SIZE 5

int buffer[BUFFER_SIZE];
int count = 0; // 当前缓冲区的大小
pthread_mutex_t mutex;
pthread_cond_t cond_full;
pthread_cond_t cond_empty;

void* producer(void* arg) {
for (int i = 0; i < 10; i++) {
pthread_mutex_lock(&mutex);
while (count == BUFFER_SIZE) { // 当缓冲区满时等待
pthread_cond_wait(&cond_empty, &mutex);
}
buffer[count++] = i; // 添加产品
printf("Produced: %d\n", i);
pthread_cond_signal(&cond_full); // 通知消费者
pthread_mutex_unlock(&mutex);
}
return NULL;
}

void* consumer(void* arg) {
for (int i = 0; i < 10; i++) {
pthread_mutex_lock(&mutex);
while (count == 0) { // 当缓冲区空时等待
pthread_cond_wait(&cond_full, &mutex);
}
int item = buffer[--count]; // 消费产品
printf("Consumed: %d\n", item);
pthread_cond_signal(&cond_empty); // 通知生产者
pthread_mutex_unlock(&mutex);
}
return NULL;
}

int main() {
pthread_t prod_thread, cons_thread;
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond_full, NULL);
pthread_cond_init(&cond_empty, NULL);

pthread_create(&prod_thread, NULL, producer, NULL);
pthread_create(&cons_thread, NULL, consumer, NULL);

pthread_join(prod_thread, NULL);
pthread_join(cons_thread, NULL);

pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond_full);
pthread_cond_destroy(&cond_empty);

return 0;
}

3. 小结

  • 本节介绍了 互斥锁条件变量 的基本概念、使用方式及示例。
  • 互斥锁用于保护临界区,确保线程安全,而条件变量使线程能够在特定条件下进行等待和通知。
  • 理解并正确使用这些同步原语对于编写高效、可靠的多线程程序至关重要。

互斥锁与条件变量

https://zglg.work/c-language-one/29/

作者

AI教程网

发布于

2024-08-08

更新于

2024-08-10

许可协议