Linux线程安全(二)条件变量实现线程同步

目录

条件变量

条件变量初始化和唤醒

键盘触发条件变量唤醒线程demo

条件变量的等待

条件变量定时等待demo

条线变量实现多线程间的同步


条件变量

条件变量是为了控制多个线程的同步工作而设计的

比如说一个系统中有多个线程的存在但有且仅有一个线程在工作,我们需要等待这个线程执行完任务之后然后唤醒另一个线程执行另外一个任务,

那这个时候"正在工作的这个线程执行完任务"就是一个条件变量,等这个条件变量触发之后正在工作的线程就会休眠,然后新的线程会启动。

条件变量初始化和唤醒

#include <pthread.h>

//销毁条件变量 int pthread_cond_destroy(pthread_cond_t *cond);

//初始化条件变量
int pthread_cond_init(pthread_cond_t *restrict cond,
const pthread_condattr_t *restrict attr);

cond:条件变量

attr:属性默认为 NULL

返回值: 成功 0 失败 -1

#include <pthread.h>

//随机唤醒一个等待的线程 int pthread_cond_signal(pthread_cond_t *cond);

//唤醒所有正在等待的线程 int pthread_cond_broadcast(pthread_cond_t *cond);

键盘触发条件变量唤醒线程demo
cpp 复制代码
#include <stdio.h>
#include <pthread.h>

pthread_cond_t cond;
pthread_mutex_t mutex;

int n = 0;

void *task(void *arg)
{
    while (1)
    {
        printf("%ld 线程等待条件\n", pthread_self());
        pthread_cond_wait(&cond, &mutex);
        if (n == 1)
        {
            n = 0;
            printf("%ld 线程被唤醒,执行任务\n", pthread_self());
        }
    }
}

int main()
{
    // 初始化锁与条件变量
    pthread_cond_init(&cond, NULL);
    pthread_mutex_init(&mutex, NULL);

    // 创建一个线程
    pthread_t tid;
    pthread_create(&tid, NULL, task, NULL);
    pthread_create(&tid, NULL, task, NULL);
    pthread_create(&tid, NULL, task, NULL);
    pthread_create(&tid, NULL, task, NULL);

    while (1)
    {
        printf("1.唤醒随机一个线程  2.唤醒所有线程\n");
        int n = 0;
        scanf("%d", &n);

        if (n == 1)
        {
            pthread_cond_signal(&cond); // 唤醒随机一个
        }
        else if (n == 2)
        {
            pthread_cond_broadcast(&cond); // 唤醒所有
        }
    }
}
条件变量的等待

#include <pthread.h>

//定时等待
int pthread_cond_timedwait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex,
const struct timespec *restrict abstime);

//一直等待
int pthread_cond_wait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex);

cond:条件变量

mutex:互斥锁

abstime:定时器

返回值:

条件变量定时等待demo
cpp 复制代码
#include <stdio.h>
#include <pthread.h>
#include <time.h>

pthread_cond_t cond;

void *task(void *arg)
{
    while (1)
    {
        printf("输入任意键唤醒线程\n");
        getchar();
        pthread_cond_signal(&cond);
    }
}

int main()
{
    // 0.初始化互斥锁
    pthread_mutex_t mutex;
    pthread_mutex_init(&mutex, NULL);

    // 1.初始化条件变量
    int ret = pthread_cond_init(&cond, NULL);
    if (ret < 0)
    {
        perror("初始化条件变量失败\n");
    }

    // 创建一个线程
    pthread_t tid;
    pthread_create(&tid, NULL, task, NULL);

    // 2.开启定时等待
    while (1)
    {
        // 设置时间
        struct timespec ts;

        //clock_gettime()获取时间函数
        //CLOCK_REALTIME:系统实时时间,可以从网络同步,也可以用户自行更改
        clock_gettime(CLOCK_REALTIME, &ts); 

#if 0  //timespec结构体,tv_sec为秒
struct timespec
{
  __time_t tv_sec;    /* Seconds.  秒*/
  __syscall_slong_t tv_nsec;  /* Nanoseconds.纳秒*/      
}           
#endif

        ts.tv_sec += 5;                     // 时间增加 5 秒
        printf("开启定时等待5秒\n");
        //pthread cond wait函数的返回值为0,代表成功等待条件变量并且收到了通知。
        //如果返回值是一个非零值,则表示函数运行出现了错误
        //需要根据错误码进行处理。
        int ret = pthread_cond_timedwait(&cond, &mutex, &ts);
        printf("等待结束 %d\n", ret);  //超时返回值110
    }
}

条线变量实现多线程间的同步

利用条件变量使三个线程轮流运作,线程1执行完之后执行线程2,线程2执行完之后执行线程3,线程3执行完之后重新执行线程1.

cpp 复制代码
#include <stdio.h>
#include <pthread.h>

// 定义三个条件
pthread_cond_t first;  // 条件1
pthread_cond_t second; // 条件2
pthread_cond_t third; // 条件3

pthread_mutex_t mutex;

void *task(void *arg)
{
    while (1)
    {
        pthread_cond_wait(&third, &mutex);
        printf("线程1运行\n");
        pthread_cond_signal(&first);
    }
}

void *task1(void *arg)
{
    while (1)
    {
        pthread_cond_wait(&first, &mutex);
        printf("线程2运行\n");
        pthread_cond_signal(&second);
    }
}

void *task2(void *arg)
{
    while (1)
    {
        pthread_cond_wait(&second, &mutex);
        printf("线程3运行\n");
        pthread_cond_signal(&third);
    }
}

int main()
{
    // 初始化条件变量与线程锁
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&first, NULL);
    pthread_cond_init(&second, NULL);
    pthread_cond_init(&third, NULL);

    // 创建三个任务线程
    pthread_t tid;
    pthread_create(&tid, NULL, task, NULL);
    pthread_t tid1;
    pthread_create(&tid1, NULL, task1, NULL);
    pthread_t tid2;
    pthread_create(&tid2, NULL, task2, NULL);

    while (1)
    {
        printf("输入任意键线程开始工作\n");
        getchar();
        pthread_cond_signal(&third);
    }
}
相关推荐
2601_9491465311 小时前
C语言语音通知接口接入教程:如何使用C语言直接调用语音预警API
c语言·开发语言
wdfk_prog11 小时前
[Linux]学习笔记系列 -- [drivers][input]input
linux·笔记·学习
七夜zippoe12 小时前
CANN Runtime任务描述序列化与持久化源码深度解码
大数据·运维·服务器·cann
盟接之桥12 小时前
盟接之桥说制造:引流品 × 利润品,全球电商平台高效产品组合策略(供讨论)
大数据·linux·服务器·网络·人工智能·制造
忆~遂愿12 小时前
ops-cv 算子库深度解析:面向视觉任务的硬件优化与数据布局(NCHW/NHWC)策略
java·大数据·linux·人工智能
湘-枫叶情缘12 小时前
1990:种下那棵不落叶的树-第6集 圆明园的对话
linux·系统架构
知南x13 小时前
【Ascend C系列课程(高级)】(1) 算子调试+调优
c语言·开发语言
Fcy64813 小时前
Linux下 进程(一)(冯诺依曼体系、操作系统、进程基本概念与基本操作)
linux·运维·服务器·进程
袁袁袁袁满13 小时前
Linux怎么查看最新下载的文件
linux·运维·服务器
代码游侠13 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法