- 互斥锁(Mutex)
- 原理:互斥锁是一种二元信号量,它只有两种状态:锁定(locked)和解锁(unlocked)。当一个进程想要访问共享资源时,它首先尝试获取互斥锁。如果互斥锁处于解锁状态,进程可以获取它并进入临界区(访问共享资源的代码段),同时将互斥锁设置为锁定状态。其他进程在互斥锁被锁定时无法获取它,只能等待,直到持有互斥锁的进程释放它。
- 示例代码(以C语言和POSIX库为例):
#include <pthread.h>
#include <stdio.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int shared_variable = 0;
void* increment(void* arg) {
pthread_mutex_lock(&mutex);
shared_variable++;
printf("Incremented shared variable: %d\n", shared_variable);
pthread_mutex_unlock(&mutex);
return NULL;
}
- 信号量(Semaphore)
- 原理:信号量是一个计数器,它的值表示可用资源的数量。进程在访问共享资源前获取信号量(将计数器减1),如果计数器的值为0,则表示资源已被占用,进程需要等待。当进程使用完共享资源后,释放信号量(将计数器加1)。与互斥锁不同,信号量可以允许多个进程同时访问共享资源,只要计数器的值大于0。
- 示例代码(以C语言和POSIX库为例):
#include <semaphore.h>
#include <stdio.h>
sem_t semaphore;
int shared_variable = 0;
void* increment(void* arg) {
sem_wait(&semaphore);
shared_variable++;
printf("Incremented shared variable: %d\n", shared_variable);
sem_post(&semaphore);
return NULL;
}
- 读写锁(Read - Write Lock)
- 原理:读写锁允许多个进程同时进行读操作,但只允许一个进程进行写操作。当有进程进行写操作时,其他进程无论是读还是写都需要等待。读写锁有两种模式:读模式和写模式。多个进程可以同时获取读锁进行读操作,而获取写锁时必须独占,其他进程不能获取任何锁。
- 示例代码(以C语言和POSIX库为例):
#include <pthread.h>
#include <stdio.h>
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
int shared_variable = 0;
void* read_value(void* arg) {
pthread_rwlock_rdlock(&rwlock);
printf("Read shared variable: %d\n", shared_variable);
pthread_rwlock_unlock(&rwlock);
return NULL;
}
void* write_value(void* arg) {
pthread_rwlock_wrlock(&rwlock);
shared_variable++;
printf("Incremented shared variable: %d\n", shared_variable);
pthread_rwlock_unlock(&rwlock);
return NULL;
}
- 文件锁
- 原理:对于文件描述符这种共享资源,可以使用文件锁来控制对文件的访问。在Linux系统中,可以使用
fcntl
函数来设置文件锁。文件锁分为建议性锁和强制性锁,建议性锁要求所有访问文件的进程都要遵守锁的规则,而强制性锁由内核强制执行。
- 示例代码(以C语言和POSIX库为例):
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main() {
int fd = open("test.txt", O_RDWR | O_CREAT, 0666);
struct flock lock;
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
fcntl(fd, F_SETLKW, &lock);
// 进行文件操作
lock.l_type = F_UNLCK;
fcntl(fd, F_SETLK, &lock);
close(fd);
return 0;
}
- 进程间通信(IPC)机制辅助
- 消息队列:通过消息队列进行进程间通信,可以将对共享资源的操作封装成消息发送到队列中,由一个专门的进程来处理这些消息,从而避免多个进程直接竞争共享资源。
- 共享内存与信号量结合:共享内存提供了一种快速的进程间共享数据的方式,但需要结合信号量来控制对共享内存区域的访问,以避免竞争。例如,进程在访问共享内存前先获取信号量,访问结束后释放信号量。