在操作系统中,进程同步是指在并发环境下,多个进程为了共享资源或协调执行而采取的机制,确保数据的一致性和正确性。由于多个进程可能同时访问共享资源,因此必须使用同步手段来避免竞态条件(Race Condition)。
🚀 常见的进程同步方法
| 同步方法 | 原理 | 适用场景 | 是否忙等待 |
|---|---|---|---|
| 🔒互斥锁 (Mutex) | 进程间互斥访问共享资源 | 简单的互斥控制 | ❌ 否 |
| 📊信号量 (Semaphore) | 计数器机制,控制资源访问上限 | 资源限制、访问控制 | ✅/❌ 可选 |
| ⏳条件变量 (Condition Variable) | 等待-通知机制,协调线程间操作 | 生产者-消费者模型、复杂同步场景 | ❌ 否 |
| 📬管道 (Pipe) | 通过管道传输数据,实现同步 | 父子进程间数据传输 | ❌ 否 |
| 📨消息队列 (Message Queue) | 内核维护的消息链表,传递消息 | 独立进程间的同步与数据传输 | ❌ 否 |
| 🧠共享内存 (Shared Memory) | 共享内存区 + 同步机制 | 大量数据传输 + 同步机制 | ❌ 否 |
| 📣信号 (Signal) | 异步机制,通知某个进程触发事件 | 中断、超时、异常处理 | ❌ 否 |
🔒 1. 互斥锁 (Mutex)
🔹 原理
- 互斥锁确保同一时刻仅有一个进程访问共享资源。
- 通过
lock()和unlock()控制访问权。
🔹 特点
✅ 适用于多进程对同一资源的访问控制;
✅ 无忙等待,效率较高;
❗ 需小心死锁问题;
🔹 示例代码 (C - pthread_mutex)
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
pthread_mutex_t lock;
int counter = 0;
void* increment(void* arg) {
for (int i = 0; i < 5; ++i) {
pthread_mutex_lock(&lock); // 加锁
counter++;
printf("线程 %ld - 计数器: %d\n", pthread_self(), counter);
pthread_mutex_unlock(&lock); // 解锁
sleep(1);
}
return NULL;
}
int main() {
pthread_t t1, t2;
pthread_mutex_init(&lock, NULL);
pthread_create(&t1, NULL, increment, NULL);
pthread_create(&t2, NULL, increment, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_mutex_destroy(&lock);
return 0;
}
📊 2. 信号量 (Semaphore)
🔹 原理
- 信号量维护一个计数器,表示可用资源的数量。
P()(wait) 操作:计数器减 1;V()(signal) 操作:计数器加 1;
🔹 特点
✅ 适合控制对有限资源的访问;
✅ 适用于多进程访问同一资源的访问上限控制;
❗ 可能会出现死锁,需小心处理;
🔹 示例代码 (C - sem_t)
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <unistd.h>
sem_t semaphore;
void* threadFunc(void* arg) {
sem_wait(&semaphore); // 获取信号量
printf("线程 %ld 正在访问共享资源\n", pthread_self());
sleep(1);
printf("线程 %ld 释放资源\n", pthread_self());
sem_post(&semaphore); // 释放信号量
return NULL;
}
int main() {
pthread_t threads[3];
sem_init(&semaphore, 0, 2); // 最多允许2个线程同时访问
for(int i = 0; i < 3; i++)
pthread_create(&threads[i], NULL, threadFunc, NULL);
for(int i = 0; i < 3; i++)
pthread_join(threads[i], NULL);
sem_destroy(&semaphore);
return 0;
}
⏳ 3. 条件变量 (Condition Variable)
🔹 原理
- 条件变量用于等待/通知机制,通常与
pthread_mutex配合使用。 wait()操作等待条件满足;signal()操作通知等待的线程继续执行;
🔹 特点
✅ 适合复杂的线程同步;
✅ 常用于生产者-消费者模型;
❗ 不适合大数据传输;
🔹 示例代码 (C - pthread_cond)
#include <pthread.h>
#include <stdio.h>
pthread_mutex_t mutex;
pthread_cond_t cond;
int ready = 0;
void* producer(void* arg) {
pthread_mutex_lock(&mutex);
ready = 1;
printf("生产者:数据已准备好\n");
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
return NULL;
}
void* consumer(void* arg) {
pthread_mutex_lock(&mutex);
while (!ready) {
pthread_cond_wait(&cond, &mutex);
}
printf("消费者:已接收数据\n");
pthread_mutex_unlock(&mutex);
return NULL;
}
int main() {
pthread_t t1, t2;
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
pthread_create(&t1, NULL, producer, NULL);
pthread_create(&t2, NULL, consumer, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
return 0;
}
📣 4. 信号 (Signal)
🔹 原理
- 信号是一种异步的通知机制,允许一个进程向另一个进程发送信号,告知其需要执行的操作。
🔹 常用信号
✅ SIGINT → 中断信号 (Ctrl+C)
✅ SIGTERM → 终止信号
✅ SIGCHLD → 子进程终止信号
🔹 示例代码 (C - signal())
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void signalHandler(int signum) {
printf("收到信号: %d\n", signum);
}
int main() {
signal(SIGINT, signalHandler); // 捕获 Ctrl+C 信号
while (1) {
printf("等待信号...\n");
sleep(2);
}
return 0;
}
📋 5. 对比总结
| 方法 | 适用场景 | 优势 | 劣势 |
|---|---|---|---|
| 互斥锁 (Mutex) | 简单的临界区访问控制 | 无忙等待、简单易用 | 不适用于多资源并发场景 |
| 信号量 (Semaphore) | 资源访问上限控制 | 适用于多资源管理 | 容易导致死锁 |
| 条件变量 (Condition Variable) | 线程间的等待/通知机制 | 复杂同步场景、无忙等待 | 需配合互斥锁使用 |
| 信号 (Signal) | 异步事件通知 | 实时性高、轻量级 | 仅适合短暂通知,不适合数据传输 |
| 共享内存 (Shared Memory) | 大量数据共享 | 数据传输最快 | 需额外借助同步机制避免数据竞争 |
🌟 推荐学习路径
- 入门阶段 → 使用
Mutex、Semaphore学习基础同步机制; - 进阶阶段 → 掌握
Condition Variable,解决更复杂的同步问题; - 高效场景 → 在大规模数据传输中使用
共享内存提高性能;
5077

被折叠的 条评论
为什么被折叠?



