可能存在的共享资源
- 内存区域:如共享内存段,多个进程可以映射到同一块物理内存,用于数据的快速交换和共享。例如,在服务器中,可能多个子进程需要读取和修改某些配置信息,这些信息可以存储在共享内存中。
- 文件:多个进程可能需要同时对同一个文件进行读写操作。比如日志文件,多个进程都可能向其中写入日志信息。
- 网络套接字:在服务器模型中,多个进程可能需要使用同一个监听套接字来接受客户端连接。例如,主进程创建监听套接字后,fork出多个子进程,这些子进程都可能需要从该监听套接字接受新的连接。
使用C语言相关机制避免竞态条件
- 信号量:
- 原理:信号量是一个整型变量,它通过计数器来控制对共享资源的访问。当信号量的值大于0时,进程可以获取信号量(将计数器减1),从而访问共享资源;当信号量的值为0时,进程会阻塞,直到信号量的值大于0。
- 示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
#include <unistd.h>
sem_t sem;
int shared_variable = 0;
void* increment(void* arg) {
for (int i = 0; i < 1000; i++) {
sem_wait(&sem);
shared_variable++;
sem_post(&sem);
}
return NULL;
}
int main() {
sem_init(&sem, 0, 1);
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, increment, NULL);
pthread_create(&thread2, NULL, increment, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
sem_destroy(&sem);
printf("Final value of shared_variable: %d\n", shared_variable);
return 0;
}
- 互斥锁(本质也是一种特殊的二元信号量):
- 原理:互斥锁只有两种状态(锁定和解锁),它用于保证在同一时间只有一个进程能够访问共享资源。当一个进程获取了互斥锁(将其锁定),其他进程就无法获取,直到该进程释放互斥锁(解锁)。
- 示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int shared_variable = 0;
void* increment(void* arg) {
for (int i = 0; i < 1000; i++) {
pthread_mutex_lock(&mutex);
shared_variable++;
pthread_mutex_unlock(&mutex);
}
return NULL;
}
int main() {
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, increment, NULL);
pthread_create(&thread2, NULL, increment, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
pthread_mutex_destroy(&mutex);
printf("Final value of shared_variable: %d\n", shared_variable);
return 0;
}
- 读写锁:
- 原理:读写锁区分了读操作和写操作。允许多个进程同时进行读操作(因为读操作不会修改共享资源,不会产生竞态条件),但只允许一个进程进行写操作,并且在写操作时不允许有其他进程进行读或写操作。
- 示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
int shared_variable = 0;
void* read_func(void* arg) {
pthread_rwlock_rdlock(&rwlock);
printf("Reading value: %d\n", shared_variable);
pthread_rwlock_unlock(&rwlock);
return NULL;
}
void* write_func(void* arg) {
pthread_rwlock_wrlock(&rwlock);
shared_variable++;
printf("Writing value: %d\n", shared_variable);
pthread_rwlock_unlock(&rwlock);
return NULL;
}
int main() {
pthread_t read_thread, write_thread;
pthread_create(&read_thread, NULL, read_func, NULL);
pthread_create(&write_thread, NULL, write_func, NULL);
pthread_join(read_thread, NULL);
pthread_join(write_thread, NULL);
pthread_rwlock_destroy(&rwlock);
return 0;
}