前言
互斥锁(Mutex) 和 读写锁(Read-Write Lock) 是两种常用的同步机制,用于保护共享资源。它们的主要区别在于对并发访问的支持方式和适用场景。
核心对比
特性 | 互斥锁(Mutex) | 读写锁(Read-Write Lock) |
---|
锁的类型 | 独占锁(Exclusive) | 读锁(共享锁) + 写锁(独占锁) |
读操作 | 同一时间只有一个线程可以访问资源 | 多个线程可以同时持有读锁 |
写操作 | 同一时间只有一个线程可以访问资源 | 同一时间只有一个线程可以持有写锁 |
并发性 | 低(完全互斥) | 高(读锁支持并发,写锁独占) |
适用场景 | 写多读少或者读写均衡的场景 | 读多写少的场景 |
复杂度 | 简单 | 相对复杂 |
性能 | 高竞争时性能较差 | 读多写少时性能较好 |
详细区别
互斥锁(Mutex)
独占性
- Mutex是一种独占锁,同一时间只有一个线程可以持有锁
- 其他线程必须等待锁释放后才能获取锁
适用场景
- 适用于写操作频繁的场景,或者读写操作均衡的场景
- 例如:修改全局变量,更新共享数据结构等
优点
- 实现简单,易于使用
- 保证数据一致性
缺点
- 并发性差,所有操作(保活读操作)都需要互斥访问
- 高竞争时性能较差
读写锁(Read-Write Lock)
读锁和写锁分离
- 读锁是共享的,多个线程可以同时持有读锁
- 写锁是独占的,同一时间只有一个线程可以持有写锁
适用场景
- 适用于读操作远多于写操作的场景
- 例如:缓存系统、配置文件读取等
优点
- 提高读操作的并发性,适合读多写少的场景
- 写操作仍然保持独占性,确保数据一致性
缺点
- 实现相对复杂
- 如果写操作频繁,性能可能不如Mutex
使用场景对比
场景 | 互斥锁(Mutex) | 读写锁(Read-Write Lock) |
---|
读多写少 | 性能较差(读操作也需要互斥) | 性能较好(读操作可以并发) |
写多读少 | 性能较好 | 性能较差(写操作需要独占) |
读写均衡 | 性能较好 | 性能一般 |
数据一致性要求高 | 适合 | 适合 |
示例
互斥锁
#include <pthread.h>
#include <stdio.h>
pthread_mutex_t mutex;
int shared_data = 0;
void* thread_func(void* arg) {
pthread_mutex_lock(&mutex); // 加锁
shared_data++; // 修改共享资源
printf("Thread %ld: shared_data = %d\n", (long)arg, shared_data);
pthread_mutex_unlock(&mutex); // 解锁
return NULL;
}
int main() {
pthread_t threads[10];
pthread_mutex_init(&mutex, NULL);
for (long i = 0; i < 10; i++) {
pthread_create(&threads[i], NULL, thread_func, (void*)i);
}
for (int i = 0; i < 10; i++) {
pthread_join(threads[i], NULL);
}
pthread_mutex_destroy(&mutex);
return 0;
}
读写锁
#include <pthread.h>
#include <stdio.h>
pthread_rwlock_t rwlock;
int shared_data = 0;
void* reader_func(void* arg) {
pthread_rwlock_rdlock(&rwlock); // 获取读锁
printf("Reader %ld: shared_data = %d\n", (long)arg, shared_data);
pthread_rwlock_unlock(&rwlock); // 释放读锁
return NULL;
}
void* writer_func(void* arg) {
pthread_rwlock_wrlock(&rwlock); // 获取写锁
shared_data++; // 修改共享资源
printf("Writer %ld: shared_data = %d\n", (long)arg, shared_data);
pthread_rwlock_unlock(&rwlock); // 释放写锁
return NULL;
}
int main() {
pthread_t readers[5], writers[5];
pthread_rwlock_init(&rwlock, NULL);
for (long i = 0; i < 5; i++) {
pthread_create(&readers[i], NULL, reader_func, (void*)i);
pthread_create(&writers[i], NULL, writer_func, (void*)i);
}
for (int i = 0; i < 5; i++) {
pthread_join(readers[i], NULL);
pthread_join(writers[i], NULL);
}
pthread_rwlock_destroy(&rwlock);
return 0;
}
性能对比
互斥锁
- 在高竞争场景下,性能较差,因为所有线程都需要竞争同一把锁
读写锁
- 在读多写少的场景下,性能较好,因为读操作可以并发执行
- 在写多读少的场景下,性能可能不如Mutex
总结
对比项 | 互斥锁(Mutex) | 读写锁(Read-Write Lock) |
---|
适用场景 | 写多读少或读写均衡 | 读多写少 |
并发性 | 低 | 高 |
实现复杂度 | 简单 | 较复杂 |
性能 | 高竞争时性能较差 | 读多写少时性能较好 |
在实际开发中,应根据具体场景选择合适的锁: | | |
- 如果需要高并发读操作,选择 读写锁
- 如果写操作频繁或读写操作均衡,选择 互斥锁