阅读量:5
在Linux中,实现进程互斥(即确保多个进程不会同时访问共享资源)的方法有多种。以下是一些常用的方法:
1. 文件锁(File Locking)
文件锁是一种通过操作系统提供的机制来控制对文件的访问。Linux提供了两种类型的文件锁:建议性锁(Advisory Locks)和强制性锁(Mandatory Locks)。
- 建议性锁:进程可以选择是否遵守锁的约定。通常使用
fcntl系统调用来实现。 - 强制性锁:操作系统强制执行锁的规则,即使进程不遵守约定也会被阻止。
#include
#include
int fd = open("lockfile", O_RDWR | O_CREAT, 0666);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
// 设置建议性锁
struct flock lock;
lock.l_type = F_WRLCK; // 写锁
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0; // 锁定整个文件
if (fcntl(fd, F_SETLK, &lock) == -1) {
perror("fcntl");
close(fd);
exit(EXIT_FAILURE);
}
// 执行临界区代码
// 释放锁
lock.l_type = F_UNLCK;
if (fcntl(fd, F_SETLK, &lock) == -1) {
perror("fcntl");
}
close(fd);
2. 信号量(Semaphores)
信号量是一种更高级的同步机制,可以用来控制对共享资源的访问。Linux提供了两种类型的信号量:命名信号量(Named Semaphores)和无名信号量(Unnamed Semaphores)。
- 命名信号量:通过名称来标识,可以在不同进程之间共享。
- 无名信号量:只能在创建它的进程中使用。
#include
#include
#include
sem_t *sem = sem_open("/my_semaphore", O_CREAT, 0666, 1);
if (sem == SEM_FAILED) {
perror("sem_open");
exit(EXIT_FAILURE);
}
// 等待信号量
if (sem_wait(sem) == -1) {
perror("sem_wait");
sem_close(sem);
exit(EXIT_FAILURE);
}
// 执行临界区代码
// 释放信号量
if (sem_post(sem) == -1) {
perror("sem_post");
}
sem_close(sem);
sem_unlink("/my_semaphore");
3. 互斥锁(Mutexes)
互斥锁是一种简单的同步机制,用于保护临界区。Linux提供了pthread_mutex_t类型的互斥锁。
#include
#include
#include
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *thread_func(void *arg) {
pthread_mutex_lock(&mutex);
// 执行临界区代码
pthread_mutex_unlock(&mutex);
return NULL;
}
int main() {
pthread_t thread1, thread2;
if (pthread_create(&thread1, NULL, thread_func, NULL) != 0) {
perror("pthread_create");
exit(EXIT_FAILURE);
}
if (pthread_create(&thread2, NULL, thread_func, NULL) != 0) {
perror("pthread_create");
exit(EXIT_FAILURE);
}
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
pthread_mutex_destroy(&mutex);
return 0;
}
4. 条件变量(Condition Variables)
条件变量通常与互斥锁一起使用,用于线程间的同步。它们允许线程在某个条件满足时等待,并在条件改变时被唤醒。
#include
#include
#include
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int ready = 0;
void *thread_func(void *arg) {
pthread_mutex_lock(&mutex);
while (!ready) {
pthread_cond_wait(&cond, &mutex);
}
// 执行临界区代码
pthread_mutex_unlock(&mutex);
return NULL;
}
int main() {
pthread_t thread;
if (pthread_create(&thread, NULL, thread_func, NULL) != 0) {
perror("pthread_create");
exit(EXIT_FAILURE);
}
// 模拟一些工作
sleep(2);
pthread_mutex_lock(&mutex);
ready = 1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
pthread_join(thread, NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
return 0;
}
这些方法各有优缺点,选择哪种方法取决于具体的应用场景和需求。文件锁适用于跨进程的同步,信号量和互斥锁适用于同一进程内的线程同步,而条件变量则常用于复杂的同步场景。