竞争条件是当多个进程或线程同时访问共享资源时,由于执行顺序的不确定性导致结果不可预测的情况。在Linux环境下,有几种主要的方法可以避免竞争条件:
最常用的同步机制,确保同一时间只有一个线程可以访问共享资源。
#include <pthread.h>
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
void* thread_function(void* arg) {
pthread_mutex_lock(&lock);
// 临界区代码
pthread_mutex_unlock(&lock);
return NULL;
}
允许有限数量的线程同时访问资源。
#include <semaphore.h>
sem_t sem;
// 初始化信号量(允许最多3个线程同时访问)
sem_init(&sem, 0, 3);
void* thread_function(void* arg) {
sem_wait(&sem);
// 临界区代码
sem_post(&sem);
return NULL;
}
用于线程间的通信,当特定条件满足时唤醒等待的线程。
#include <pthread.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int condition = 0;
// 等待线程
void* waiting_thread(void* arg) {
pthread_mutex_lock(&mutex);
while (condition == 0) {
pthread_cond_wait(&cond, &mutex);
}
// 条件满足后的处理
pthread_mutex_unlock(&mutex);
return NULL;
}
// 通知线程
void* signaling_thread(void* arg) {
pthread_mutex_lock(&mutex);
condition = 1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
return NULL;
}
用于进程间同步访问文件。
#include <fcntl.h>
#include <unistd.h>
int fd = open("shared_file", O_RDWR);
// 获取排他锁
struct flock lock;
lock.l_type = F_WRLCK;
lock.l_start = 0;
lock.l_whence = SEEK_SET;
lock.l_len = 0; // 锁定整个文件
fcntl(fd, F_SETLKW, &lock); // 阻塞等待锁
// 处理文件
lock.l_type = F_UNLCK;
fcntl(fd, F_SETLK, &lock); // 释放锁
对于简单的计数器等操作,可以使用原子操作避免锁的开销。
#include <stdatomic.h>
atomic_int counter = ATOMIC_VAR_INIT(0);
void increment() {
atomic_fetch_add(&counter, 1);
}
pthread_rwlock_t
选择适当的同步机制取决于您的具体需求,包括性能要求、代码复杂度和可维护性等因素。