00000008_C并发编程与多线程

并发编程与多线程

并发编程在 C 语言中的应用非常广泛,特别是在高性能计算、服务器开发和嵌入式系统中。并发编程是一种设计思想,而多线程则是其常见的实现方式。虽然 C11 标准引入了对多线程的支持,但在很多应用中,POSIX 线程(pthread)仍占据主导地位,尤其是在跨平台开发和操作系统底层编程中。POSIX 线程提供了一套标准化的多线程编程接口,涵盖了线程创建、同步机制(如互斥锁、条件变量等)以及线程管理等功能,这使其成为实现高效并发应用的首选工具。

接下来,我们将深入探讨如何使用 POSIX 线程进行多线程编程。

1. POSIX线程(pthread)

1.1 线程的创建、终止与同步

在C语言中,使用pthread库进行多线程编程时,常用的操作包括创建线程、终止线程和等待线程结束。

1.1.1 线程的创建与终止

线程创建是通过pthread_create()函数来实现的,该函数原型如下:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, 
                   void *(*start_routine)(void *), void *arg);
  • thread:返回创建的线程ID。
  • attr:线程的属性,通常传入NULL表示使用默认属性。
  • start_routine:线程执行的函数。
  • arg:传递给线程函数的参数。

线程的终止使用pthread_exit()或返回的方式,一旦线程执行完start_routine函数的代码,线程会自动退出。

创建线程的简单示例:

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

void* print_message(void* msg) {
   
    printf("%s\n", (char*)msg);
    return NULL;
}

int main() {
   
    pthread_t thread;
    char *message = "Hello, World!";
    pthread_create(&thread, NULL, print_message, (void*)message);
    pthread_join(thread, NULL);  // 等待线程结束
    return 0;
}
1.1.2 线程的同步

线程同步是为了避免多个线程并发访问共享资源时发生数据竞争,常用的同步机制有互斥锁、条件变量和信号量。

1.2 线程间通信:条件变量与信号量

1.2.1 条件变量

条件变量用于线程之间的同步,允许一个线程在某个条件成立时通知另一个线程继续执行。

pthread_cond_wait()函数用于阻塞线程,直到收到条件变量的通知。其原型如下:

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
  • cond:条件变量。
  • mutex:互斥锁,必须先加锁。

条件变量的使用示例:

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

pthread_mutex_t mutex;
pthread_cond_t cond;

void* wait_for_signal(void* arg) {
   
    pthread_mutex_lock(&mutex);
    printf("Waiting for condition...\n");
    pthread_cond_wait(&cond, &mutex);
    printf("Condition met, thread resuming.\n");
    pthread_mutex_unlock(&mutex);
    return NULL;
}

void* signal_condition(void* arg) {
   
    pthread_mutex_lock(&mutex);
    printf("Signaling condition...\n");
    pthread_cond_signal(&cond);  // 通知等待线程
    pthread_mutex_unlock(&mutex);
    return NULL;
}

int main() {
   
    pthread_t thread1, thread2;
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);

    pthread_create(&thread1, NULL, wait_for_signal, NULL);
    pthread_create(&thread2, NULL, signal_condition, NULL);

    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
    return 0;
}

注意事项:

  1. pthread_cond_wait()必须在互斥锁保护下调用,因为它会释放锁并进入阻塞状态,避免其他线程在未同步的情况下修改共享数据。
  2. 条件变量唤醒时,最好使用pthread_cond_wait的循环,因为可能存在虚假唤醒(即不等条件满足时,线程也会被唤醒)。
1.2.2 信号量

信号量用于控制对资源的访问,尤其是在并发量较高时进行资源的计数管理。POSIX信号量在semaphore.h中定义,使用sem_wait()sem_post()等函数来进行操作。

信号量的简单使用示例:

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

sem_t sem;

void* thread_func(void* arg) {
   
    sem_wait(&sem);  // 信号量减1
    printf("Thread is running.\n");
    sem_post(&sem);  // 信号量加1
    return NULL;
}

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

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

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

    sem_destroy(&sem);
    return 0;
}

在这个例子中,信号量用于限制同时运行的线程数量为3。

2. 线程同步与互斥

2.1 互斥锁

互斥锁用于保护共享资源,防止多个线程同时访问时发生数据竞争。

互斥锁的创建、使用和销毁:

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

pthread_mutex_lock(&mutex);
// 执行临界区代码
pthread_mutex_unlock(&mutex);
2.2 读写锁

读写锁(pthread_rwlock_t)允许多个读线程并发执行,但写线程访问时是独占的。

pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;

// 读操作
pthread_rwlock_rdlock(&rwlock);
// 执行读操作
pthread_rwlock_unlock(&rwlock);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值