在Linux中,实现进程互斥(即确保多个进程不会同时访问共享资源)的方法有多种。以下是一些常用的方法:
文件锁是一种通过操作系统提供的机制来控制对文件的访问。Linux提供了两种类型的文件锁:建议性锁(Advisory Locks)和强制性锁(Mandatory Locks)。
fcntl系统调用来实现。#include <sys/file.h>
#include <unistd.h>
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);
信号量是一种更高级的同步机制,可以用来控制对共享资源的访问。Linux提供了两种类型的信号量:命名信号量(Named Semaphores)和无名信号量(Unnamed Semaphores)。
#include <semaphore.h>
#include <fcntl.h>
#include <unistd.h>
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");
互斥锁是一种简单的同步机制,用于保护临界区。Linux提供了pthread_mutex_t类型的互斥锁。
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
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;
}
条件变量通常与互斥锁一起使用,用于线程间的同步。它们允许线程在某个条件满足时等待,并在条件改变时被唤醒。
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
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;
}
这些方法各有优缺点,选择哪种方法取决于具体的应用场景和需求。文件锁适用于跨进程的同步,信号量和互斥锁适用于同一进程内的线程同步,而条件变量则常用于复杂的同步场景。