在Linux多线程编程中,多个线程并发访问同一块内存可能导致数据竞争、不一致等问题。以下是解决这些问题的几种主要方法:
最常用的同步机制,确保同一时间只有一个线程能访问共享资源。
#include <pthread.h>
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
int shared_data = 0;
void* thread_func(void* arg) {
pthread_mutex_lock(&lock);
// 临界区开始
shared_data++;
// 临界区结束
pthread_mutex_unlock(&lock);
return NULL;
}
适用于读多写少的场景,允许多个读线程同时访问。
#include <pthread.h>
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
void* reader_thread(void* arg) {
pthread_rwlock_rdlock(&rwlock);
// 读取共享数据
pthread_rwlock_unlock(&rwlock);
return NULL;
}
void* writer_thread(void* arg) {
pthread_rwlock_wrlock(&rwlock);
// 修改共享数据
pthread_rwlock_unlock(&rwlock);
return NULL;
}
用于线程间通信,常与互斥锁配合使用。
#include <pthread.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int ready = 0;
void* producer(void* arg) {
pthread_mutex_lock(&mutex);
ready = 1;
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);
}
// 使用共享数据
pthread_mutex_unlock(&mutex);
return NULL;
}
对于简单的数据类型,可以使用原子操作避免锁的开销。
#include <stdatomic.h>
atomic_int counter = ATOMIC_VAR_INIT(0);
void* thread_func(void* arg) {
atomic_fetch_add(&counter, 1); // 原子递增
return NULL;
}
如果可能,将数据变为线程局部存储可以完全避免同步问题。
#include <pthread.h>
pthread_key_t key;
void* thread_func(void* arg) {
int* data = malloc(sizeof(int));
*data = 42;
pthread_setspecific(key, data);
// 获取线程特定数据
int* my_data = pthread_getspecific(key);
free(my_data);
return NULL;
}
适用于高级场景,使用CAS(Compare-And-Swap)等原子操作实现无锁数据结构。
#include <stdatomic.h>
atomic_int lock = ATOMIC_VAR_INIT(0);
void acquire_lock() {
while (atomic_exchange(&lock, 1)) {
// 自旋等待
}
}
void release_lock() {
atomic_store(&lock, 0);
}
选择哪种方案取决于具体场景、性能需求和开发复杂度。对于大多数应用,互斥锁和条件变量已经足够。