C语言并发控制访问

C语言中实现并发访问控制通常涉及到使用互斥锁、信号量、条件变量等同步机制。这些机制通常通过POSIX线程库(pthread)来实现。POSIX线程主要适用于Unix-like系统,如果用户是在Windows环境下,可能需要使用不同的API,如Windows线程库。但通常情况下,C语言的并发控制讨论多基于pthread.

在 C 语言中实现并发访问控制,主要通过 多线程同步机制 和 进程间通信(IPC) 来保证共享资源的安全访问。

1. 多线程并发控制(POSIX Threads)

适用于线程间的共享资源访问控制。

(1) 互斥锁(Mutex)

通过锁机制确保同一时间只有一个线程访问共享资源。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stdio.h>
#include <pthread.h>

// 全局共享资源
int counter = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

// 线程函数
void* increment(void* arg) {
for (int i = 0; i < 100000; i++) {
pthread_mutex_lock(&mutex); // 加锁
counter++;
pthread_mutex_unlock(&mutex); // 解锁
}
return NULL;
}

int main() {
pthread_t t1, t2;

pthread_create(&t1, NULL, increment, NULL);
pthread_create(&t2, NULL, increment, NULL);

pthread_join(t1, NULL);
pthread_join(t2, NULL);

printf("Final counter value: %d\n", counter); // 正确输出 200000
pthread_mutex_destroy(&mutex);
return 0;
}

(2) 信号量(Semaphore)

通过计数器控制并发访问的线程数量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>

#define MAX_CONCURRENT 3

sem_t sem;

void* task(void* arg) {
sem_wait(&sem); // 信号量-1
printf("Thread %ld accessing resource...\n", (long)arg);
sleep(1); // 模拟耗时操作
sem_post(&sem); // 信号量+1
return NULL;
}

int main() {
pthread_t threads[5];
sem_init(&sem, 0, MAX_CONCURRENT); // 初始化信号量

for (long i = 0; i < 5; i++) {
pthread_create(&threads[i], NULL, task, (void*)i);
}

for (int i = 0; i < 5; i++) {
pthread_join(threads[i], NULL);
}

sem_destroy(&sem);
return 0;
}

(3) 条件变量(Condition Variable)

用于线程间的状态通知与等待。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <pthread.h>

int data_ready = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

// 生产者线程
void* producer(void* arg) {
pthread_mutex_lock(&mutex);
// 生产数据...
data_ready = 1;
pthread_cond_signal(&cond); // 通知消费者
pthread_mutex_unlock(&mutex);
return NULL;
}

// 消费者线程
void* consumer(void* arg) {
pthread_mutex_lock(&mutex);
while (!data_ready) {
pthread_cond_wait(&cond, &mutex); // 等待条件满足
}
// 消费数据...
data_ready = 0;
pthread_mutex_unlock(&mutex);
return NULL;
}

2. 多进程并发控制(IPC)

适用于进程间的共享资源访问控制。

(1) 文件锁(fcntl)

通过文件锁控制对共享文件的访问。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <fcntl.h>
#include <unistd.h>

int main() {
int fd = open("shared_file.txt", 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); // 解锁
close(fd);
return 0;
}

(2) 信号量(System V Semaphore)

通过系统级信号量控制进程间并发。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <sys/sem.h>
#include <stdio.h>

int main() {
key_t key = ftok("/tmp", 'a');
int sem_id = semget(key, 1, IPC_CREAT | 0666);
semctl(sem_id, 0, SETVAL, 1); // 初始值1(二进制信号量)

struct sembuf op;
op.sem_num = 0;
op.sem_op = -1; // P操作(等待)
op.sem_flg = 0;
semop(sem_id, &op, 1);

// 临界区操作...

op.sem_op = 1; // V操作(释放)
semop(sem_id, &op, 1);
semctl(sem_id, 0, IPC_RMID); // 删除信号量
return 0;
}

3. 高级机制

(1) 读写锁(Read-Write Lock)

允许多个读线程同时访问,但写线程独占资源。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;

// 读线程
void* reader(void* arg) {
pthread_rwlock_rdlock(&rwlock);
// 读取共享资源...
pthread_rwlock_unlock(&rwlock);
return NULL;
}

// 写线程
void* writer(void* arg) {
pthread_rwlock_wrlock(&rwlock);
// 修改共享资源...
pthread_rwlock_unlock(&rwlock);
return NULL;
}

(2) 原子操作(C11标准)

C11 标准支持原子类型,适用于简单变量的无锁操作。

1
2
3
4
5
6
7
#include <stdatomic.h>

atomic_int counter = ATOMIC_VAR_INIT(0);

void increment() {
atomic_fetch_add(&counter, 1);
}