pthread 条件变量使用详解

pthread 条件变量使用

  • 条件变量:多线程中常用的一种同步机制。通常与互斥锁结合使用,用于实现线程之间的等待和通知机制。
  • 条件变量提供了线程间的通信方式,其中一个线程可以等待某个条件满足,而另一个线程可以通知条件已经满足。
  • 允许线程在某个特定的条件下进行等待,而不是占用 CPU 资源进行轮询检查。
  • 通常用于解决生产者-消费者问题、读者-写者问题以及其他需要线程间同步的场景。
  • 在使用条件变量时,需要搭配互斥锁以确保线程安全。当一个线程等待条件满足时,它会释放互斥锁,并等待其他线程通知。一旦收到通知,它会重新尝试获取互斥锁以进行后续操作。
  • 在使用条件变量时要避免出现竞态条件(Race Condition),即在等待条件和接收通知之间可能发生的状态改变。因此,通常使用 while 循环来检查条件是否满足,而不是使用 if 语句。

pthread_cond_init

  • 函数原型:

    int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
    
    • cond:指向条件变量的指针。
    • attr:指向条件变量属性的指针,通常设置为 NULL,表示使用默认属性。
  • 用于初始化条件变量。

  • 使用条件变量时,应该先初始化再使用,最后再销毁。

pthread_cond_destroy

  • 函数原型:

    int pthread_cond_destroy(pthread_cond_t *cond);
    
    • cond:指向条件变量的指针。
  • 用于销毁条件变量,并释放与之相关的资源。

  • 在销毁条件变量之前,需要确保没有任何线程在等待或正在使用该条件变量。

  • 条件变量通常与互斥锁一起使用,因此在销毁条件变量之前,还需要确保相关的互斥锁已经被销毁。条件变量和互斥锁的销毁顺序应该与它们的创建顺序相反。

pthread_cond_wait

  • 函数原型:

    int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
    
    • cond:指向条件变量的指针。
    • mutex:指向互斥锁的指针。
    • 返回值:成功返回 0,失败返回错误代码。
  • 用于等待条件变量被唤醒。

  • 调用该函数之前,必须先获得互斥锁 mutex。

  • 在等待期间,互斥锁会自动释放,并使当前线程处于阻塞状态,直到条件变量被唤醒并且重新获得互斥锁为止。

pthread_cond_timedwait

  • 函数原型:

    int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);
    
    • cond:指向条件变量的指针。
    • mutex:指向互斥锁的指针。
    • abstime:指向结构体 timespec 的指针,表示等待的绝对时间。
    • 返回值:成功返回 0,失败返回错误代码。
  • 用于在指定的时间内等待条件变量被唤醒。如果在等待过程中条件变量被唤醒,则返回 0;如果等待超时,则返回 ETIMEDOUT;如果出现其他错误,则返回错误码。

  • 调用该函数之前,必须先获得互斥锁 mutex。

  • 在等待期间,互斥锁会自动释放,并使当前线程处于阻塞状态,直到条件变量被唤醒并且重新获得互斥锁为止。

pthread_cond_signal

  • 函数原型:

    int pthread_cond_signal(pthread_cond_t *cond);
    
    • cond:指向条件变量的指针。
  • 用于唤醒等待条件变量的一个线程。

  • 如果有多个线程在等待条件变量,则会唤醒其中一个线程。

  • 如果没有线程在等待条件变量,则该函数不会产生任何效果。

pthread_cond_broadcast

  • 函数原型:

    int pthread_cond_broadcast(pthread_cond_t *cond);
    
    • cond:指向条件变量的指针。
  • 用于唤醒所有等待条件变量的线程。

  • 如果没有线程在等待该条件变量,则该函数不会产生任何效果。

示例

  • 以下示例演示了条件变量的基本使用:一个线程更改变量值, 另一个线程等待变量值被更改后再使用。

    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <errno.h>
    #include <unistd.h>
    
    int var = 10;
    pthread_cond_t g_cond;
    pthread_mutex_t g_mutex;
    
    void* thread1_func(void* arg)
    {
        // 必须先获取互斥锁
        pthread_mutex_lock(&g_mutex);
    
        sleep(1);
        var = 100;
        printf("thread1, change var to %d \n", var);
    
        // 解锁
        pthread_mutex_unlock(&g_mutex);
    
        // 唤醒等待该条件变量的一个线程
        pthread_cond_signal(&g_cond);
        return NULL;
    }
    
    void* thread2_func(void* arg)
    {
        // 必须先获取互斥锁
        pthread_mutex_lock(&g_mutex);
    
        // 获取当前时间
        struct timespec ts;
        clock_gettime(CLOCK_REALTIME, &ts);
        // 设置等待时间为 5 秒
        ts.tv_sec += 5;
    
        // 等待条件变量被唤醒,或者等待时间超时
        // 在等待期间,互斥锁会自动释放,并使当前线程处于阻塞状态,直到条件变量被唤醒并且重新获得互斥锁为止
        printf("thread2, waiting cond signal\n");
        int ret = pthread_cond_timedwait(&g_cond, &g_mutex, &ts);
        if (ret == 0) {
            // 条件变量被唤醒并且已经持有互斥锁
            printf("thread2, get cond signaled\n");
        } else if (ret == ETIMEDOUT) {
            printf("thread2, wait timed out\n");
        } else {
            printf("thread2, wait failed\n");
        }
    
        printf("thread2, get var %d\n", var);
    
        // 解锁
        pthread_mutex_unlock(&g_mutex);
        return NULL;
    }
    
    int main()
    {
        // 初始化条件变量
        pthread_cond_init(&g_cond, NULL);
        // 初始化互斥锁
        pthread_mutex_init(&g_mutex, NULL);
    
        // 创建线程
        pthread_t th1;
        pthread_t th2;
        pthread_create(&th2, NULL, thread2_func, NULL);
        // 让线程 2 先运行
        sleep(1);
        pthread_create(&th1, NULL, thread1_func, NULL);
    
        // 等待线程结束
        pthread_join(th1, NULL);
        pthread_join(th2, NULL);
    
        // 销毁互斥锁
        pthread_mutex_destroy(&g_mutex);
        // 销毁条件变量
        pthread_cond_destroy(&g_cond);
        return 0;
    }
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
pthread_create函数用于创建一个新的线程,其原型如下: ``` int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); ``` 参数说明: - `thread`:指向 `pthread_t` 类型的指针,用于存储新创建线程的标识符。 - `attr`:指向 `pthread_attr_t` 类型的指针,用于设置新创建线程的属性。如果为 NULL,则使用默认属性。 - `start_routine`:指向函数的指针,新创建线程的执行将从此函数开始。这个函数必须返回一个指向 `void` 的指针,并且它的唯一参数是一个指向 `void` 的指针。 - `arg`:传递给 `start_routine` 的参数。 函数返回值: - 如果成功创建了新线程,pthread_create 函数返回 0。 - 如果出现错误,pthread_create 函数返回一个正整数错误码。 下面是一个例子,展示如何使用 pthread_create 函数创建一个新线程: ``` #include <stdio.h> #include <stdlib.h> #include <pthread.h> void *thread_function(void *arg) { int thread_arg = *(int *)arg; printf("Hello from thread %d\n", thread_arg); return NULL; } int main() { pthread_t thread; int thread_arg = 1234; int res = pthread_create(&thread, NULL, thread_function, &thread_arg); if (res != 0) { perror("pthread_create failed"); exit(EXIT_FAILURE); } printf("Created thread %ld\n", (long)thread); pthread_exit(NULL); // 等待新线程结束 } ``` 在这个例子中,我们首先定义了一个函数 thread_function,它将作为新创建线程的执行函数。我们将一个整数变量 thread_arg 作为参数传递给这个函数。在 thread_function 中,我们将这个参数打印出来。 在 main 函数中,我们首先创建了一个整数变量 thread_arg,并将其传递给 pthread_create 函数。pthread_create 函数会创建一个新的线程,并将 thread_function 函数指定为该线程的执行函数。在我们的示例中,我们将新线程的标识符存储在 pthread_t 类型的变量 thread 中。如果 pthread_create 函数返回错误,则程序将退出。否则,我们将新线程的标识符打印出来,并等待新线程结束。 以上就是 pthread_create 函数的详细介绍。需要注意的是,创建线程后,我们需要使用 pthread_join 函数等待新线程结束,并释放新线程所占用的资源。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

专注的罗哈哈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值