C语言中互斥锁、信号量和条件变量的所有相关函数、参数、返回值和说明

1. 互斥锁(Mutex)的使用

互斥锁用于保护共享数据,防止多个线程同时修改它。

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

// 定义一个全局共享变量
int shared_counter = 0;
// 定义一个互斥锁
pthread_mutex_t mutex;

void* increment_counter(void* arg) {
    for (int i = 0; i < 100000; ++i) {
        // 锁定互斥锁
        pthread_mutex_lock(&mutex);
        
        // 修改共享变量
        shared_counter++;
        
        // 解锁互斥锁
        pthread_mutex_unlock(&mutex);
    }
    return NULL;
}

int main() {
    // 初始化互斥锁
    if (pthread_mutex_init(&mutex, NULL) != 0) {
        printf("Mutex init failed\n");
        return 1;
    }

    pthread_t thread1, thread2;

    // 创建两个线程同时运行
    pthread_create(&thread1, NULL, increment_counter, NULL);
    pthread_create(&thread2, NULL, increment_counter, NULL);

    // 等待两个线程完成
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    // 打印计数结果
    printf("Final counter value: %d\n", shared_counter);

    // 销毁互斥锁
    pthread_mutex_destroy(&mutex);
    return 0;
}

2. 信号量(Semaphore)的使用

信号量通过计数器控制资源访问,允许多个线程访问有限的资源。

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

#define NUM_RESOURCES 2

// 定义信号量
sem_t semaphore;

void* access_resource(void* arg) {
    int thread_num = *(int*)arg;

    // 等待信号量
    sem_wait(&semaphore);
    
    // 模拟资源访问
    printf("Thread %d accessing resource\n", thread_num);
    sleep(1);  // 模拟工作
    printf("Thread %d finished\n", thread_num);

    // 增加信号量, 释放资源
    sem_post(&semaphore);
    return NULL;
}

int main() {
    // 初始化信号量
    sem_init(&semaphore, 0, NUM_RESOURCES);

    pthread_t threads[5];

    for (int i = 0; i < 5; ++i) {
        int* thread_num = malloc(sizeof(int));
        *thread_num = i + 1;        
        pthread_create(&threads[i], NULL, access_resource, thread_num);
    }

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

    // 销毁信号量
    sem_destroy(&semaphore);
    return 0;
}

3. 条件变量(Condition Variable)的使用

条件变量用于线程间的事件通知,一个线程等待条件变化时释放锁,直到其他线程发出信号。

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

pthread_mutex_t mutex;
pthread_cond_t cond_var;
int ready = 0;  // 状态标记

void* wait_for_event(void* arg) {
    pthread_mutex_lock(&mutex);

    // 等待 ready 被设置为1
    while (!ready) {
        printf("Thread waiting\n");
        pthread_cond_wait(&cond_var, &mutex);
    }

    printf("Thread proceeded after condition met\n");
    pthread_mutex_unlock(&mutex);
    return NULL;
}

void* signal_event(void* arg) {
    pthread_mutex_lock(&mutex);
    ready = 1;  // 改变条件
    pthread_cond_signal(&cond_var);  // 发送信号

    printf("Thread signaled\n");
    pthread_mutex_unlock(&mutex);
    return NULL;
}

int main() {
    pthread_t thread1, thread2;

    // 初始化互斥锁和条件变量
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond_var, NULL);

    pthread_create(&thread1, NULL, wait_for_event, NULL);
    sleep(1);  // 确保第一个线程先运行
    pthread_create(&thread2, NULL, signal_event, NULL);

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

    // 销毁互斥锁和条件变量
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond_var);

    return 0;
}

<think>好的,用户想了解在C语言中如何使用信号量。我需要先回忆一下信号量的基本概念它们在多线程或多进程编程中的作用。信号量主要用于控制对共享资源的访问,防止竞态条件。 首先,应该确定用户是问线程间的信号量还是进程间的,因为两者的实现可能不同。POSIX信号量有两种:一种是线程间使用的(匿名信号量),另一种是进程间使用的(命名信号量)。但用户可能只是需要基础的使用方法,所以应该涵盖这两种情况。 接下来,需要介绍信号量的基本操作:初始化(sem_init)、等待(sem_wait)、发布(sem_post)销毁(sem_destroy)。对于命名信号量,可能还需要提到sem_opensem_unlink。 然后,可能需要一个简单的例子来说明,比如使用信号量控制两个线程对共享变量的访问。这个例子应该包括必要的头文件,比如semaphore.h,以及正确使用函数调用的步骤。 同时,要注意错误处理,比如检查sem_init的返回值,但在示例中可能为了简洁而省略,但实际应用中应该加上。此外,需要说明编译时需要链接pthread库,比如使用gcc -pthread。 另外,用户可能会混淆信号量互斥锁的区别,可以简要提及信号量更适合控制多个资源的访问,而互斥锁是二进制信号量的一种特例。 最后,确保回答结构清晰,分步骤说明,并给出代码示例。同时提醒命名信号量的使用场景,比如跨进程的情况,以及使用后的清理工作,如关闭删除命名信号量。</think>在C语言中,信号量(semaphore)是用于多线程/多进程同步的核心工具,主要通过`semaphore.h`头文件实现。以下是分步骤详解: --- ### **一、信号量基本操作** 1. **创建信号量** ```c sem_t sem; // 声明信号量变量 int ret = sem_init(&sem, 0, 1); // 初始化 // 参数2:0表示线程间共享,1表示进程间共享 // 参数3:初始值(代表可用资源数) ``` 2. **等待信号量(P操作)** ```c sem_wait(&sem); // 原子操作,若值>0则减1,否则阻塞 ``` 3. **释放信号量(V操作)** ```c sem_post(&sem); // 原子操作,信号量值加1 ``` 4. **销毁信号量** ```c sem_destroy(&sem); // 必须在使用完毕后销毁 ``` --- ### **二、线程同步示例** ```c #include <stdio.h> #include <pthread.h> #include <semaphore.h> sem_t sem; // 全局信号量 int counter = 0; void* thread_func(void* arg) { sem_wait(&sem); // 进入临界区前获取信号量 for(int i=0; i<1000000; i++) counter++; sem_post(&sem); // 退出临界区后释放 return NULL; } int main() { sem_init(&sem, 0, 1); // 初始化信号量为1 pthread_t t1, t2; pthread_create(&t1, NULL, thread_func, NULL); pthread_create(&t2, NULL, thread_func, NULL); pthread_join(t1, NULL); pthread_join(t2, NULL); printf("Final counter: %d\n", counter); // 正确输出2000000 sem_destroy(&sem); return 0; } ``` > 编译需添加`-pthread`参数:`gcc -pthread demo.c` --- ### **三、命名信号量(进程间通信)** ```c #include <fcntl.h> #include <sys/stat.h> sem_t *sem = sem_open("/my_sem", O_CREAT, 0644, 1); // 创建命名信号量 sem_wait(sem); // 使用方式与匿名信号量相同 sem_post(sem); sem_close(sem); // 关闭信号量 sem_unlink("/my_sem"); // 彻底删除系统资源 ``` --- ### **四、重要注意事项** 1. **信号量 vs 互斥锁** - 互斥锁(mutex)是二值信号量的特例 - 信号量可控制多个资源的访问(初始值>1时) 2. **错误处理** ```c if(sem_init(&sem, 0, 1) == -1) { perror("sem_init failed"); exit(EXIT_FAILURE); } ``` 3. **死锁预防** - 确保每个`sem_wait()`都有对应的`sem_post()` - 避免嵌套使用时顺序错误 信号量是解决生产者-消费者问题、读写锁实现等复杂同步场景的基础工具,正确使用可有效避免竞态条件(race condition)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值