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