跳到主要内容

C 语言并发模式

并发编程是现代软件开发中的一个重要概念,尤其是在需要同时处理多个任务的场景中。C语言通过多线程和并发模式提供了强大的工具来实现高效的并发编程。本文将介绍C语言中的并发模式,并通过代码示例和实际案例帮助你理解其应用。

什么是并发模式?

并发模式是指在程序中同时执行多个任务的方式。这些任务可以是独立的,也可以是相互依赖的。在C语言中,并发通常通过多线程来实现。多线程允许程序在同一时间内执行多个线程,从而提高程序的效率和响应速度。

基本概念

线程

线程是操作系统能够进行运算调度的最小单位。一个进程可以包含多个线程,这些线程共享进程的资源,但每个线程有自己的栈和寄存器。

互斥锁

互斥锁(Mutex)是一种用于保护共享资源的机制。当一个线程持有互斥锁时,其他线程必须等待该锁被释放后才能访问共享资源。

条件变量

条件变量(Condition Variable)用于线程间的同步。它允许线程在某些条件不满足时进入等待状态,并在条件满足时被唤醒。

代码示例

创建线程

以下是一个简单的C语言程序,展示了如何创建和启动一个线程:

c
#include <stdio.h>
#include <pthread.h>

void* thread_function(void* arg) {
printf("Hello from thread!\n");
return NULL;
}

int main() {
pthread_t thread_id;
pthread_create(&thread_id, NULL, thread_function, NULL);
pthread_join(thread_id, NULL);
printf("Main thread exiting.\n");
return 0;
}

输出:

Hello from thread!
Main thread exiting.

使用互斥锁

以下示例展示了如何使用互斥锁来保护共享资源:

c
#include <stdio.h>
#include <pthread.h>

int shared_resource = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void* increment_resource(void* arg) {
for (int i = 0; i < 100000; i++) {
pthread_mutex_lock(&mutex);
shared_resource++;
pthread_mutex_unlock(&mutex);
}
return NULL;
}

int main() {
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, increment_resource, NULL);
pthread_create(&thread2, NULL, increment_resource, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
printf("Shared resource value: %d\n", shared_resource);
return 0;
}

输出:

Shared resource value: 200000

使用条件变量

以下示例展示了如何使用条件变量来实现线程间的同步:

c
#include <stdio.h>
#include <pthread.h>

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

void* producer(void* arg) {
pthread_mutex_lock(&mutex);
ready = 1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
return NULL;
}

void* consumer(void* arg) {
pthread_mutex_lock(&mutex);
while (ready == 0) {
pthread_cond_wait(&cond, &mutex);
}
printf("Resource is ready!\n");
pthread_mutex_unlock(&mutex);
return NULL;
}

int main() {
pthread_t producer_thread, consumer_thread;
pthread_create(&producer_thread, NULL, producer, NULL);
pthread_create(&consumer_thread, NULL, consumer, NULL);
pthread_join(producer_thread, NULL);
pthread_join(consumer_thread, NULL);
return 0;
}

输出:

Resource is ready!

实际案例

生产者-消费者问题

生产者-消费者问题是一个经典的并发问题,涉及两个线程:一个生产者线程和一个消费者线程。生产者线程生成数据并将其放入缓冲区,而消费者线程从缓冲区中取出数据并进行处理。

c
#include <stdio.h>
#include <pthread.h>

#define BUFFER_SIZE 10

int buffer[BUFFER_SIZE];
int count = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_producer = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond_consumer = PTHREAD_COND_INITIALIZER;

void* producer(void* arg) {
for (int i = 0; i < 20; i++) {
pthread_mutex_lock(&mutex);
while (count == BUFFER_SIZE) {
pthread_cond_wait(&cond_producer, &mutex);
}
buffer[count++] = i;
printf("Produced: %d\n", i);
pthread_cond_signal(&cond_consumer);
pthread_mutex_unlock(&mutex);
}
return NULL;
}

void* consumer(void* arg) {
for (int i = 0; i < 20; i++) {
pthread_mutex_lock(&mutex);
while (count == 0) {
pthread_cond_wait(&cond_consumer, &mutex);
}
int item = buffer[--count];
printf("Consumed: %d\n", item);
pthread_cond_signal(&cond_producer);
pthread_mutex_unlock(&mutex);
}
return NULL;
}

int main() {
pthread_t producer_thread, consumer_thread;
pthread_create(&producer_thread, NULL, producer, NULL);
pthread_create(&consumer_thread, NULL, consumer, NULL);
pthread_join(producer_thread, NULL);
pthread_join(consumer_thread, NULL);
return 0;
}

输出:

Produced: 0
Consumed: 0
Produced: 1
Consumed: 1
...
Produced: 19
Consumed: 19

总结

C语言中的并发模式通过多线程、互斥锁和条件变量等机制,使得程序能够高效地处理多个任务。理解这些基本概念并通过实际案例进行练习,将帮助你掌握并发编程的核心技能。

附加资源与练习

  • 练习1:修改生产者-消费者问题的代码,使其支持多个生产者和多个消费者。
  • 练习2:尝试使用信号量(Semaphore)来实现线程同步。
  • 推荐阅读
    • 《C Programming: A Modern Approach》 by K. N. King
    • 《The C Programming Language》 by Brian W. Kernighan and Dennis M. Ritchie
提示

在编写并发程序时,务必注意线程安全和资源竞争问题,避免死锁和竞态条件。