当前位置: 首页 > article >正文

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
#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
#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.

#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);
    }
}


http://www.kler.cn/a/372666.html

相关文章:

  • 论文提交步骤 | 2024年第五届MathorCup大数据竞赛
  • 前端好用的网站分享——CSS(持续更新中)
  • 书生实战营第四期-第三关 Git+InternStudio
  • 【Mac】Python 环境管理工具
  • Docker部署教程:打造流畅的斗地主网页小游戏
  • 【总目录】
  • Logstash 迁移索引元数据(设置和映射)
  • Word中遇到的问题记录(页眉,页码分节符,跨页断行)
  • 《Web性能权威指南》-浏览器API与协议-读书笔记
  • 搭建普通 Spring IoC 项目
  • 白立新:人工智能爆发,倒逼人类走向“三体全能”
  • 阿里巴巴店铺商品API返回值中的商品分类与筛选条件
  • QT如何给视频打时标
  • PG数据库之事务处理
  • 域渗透AD渗透攻击利用 python脚本攻击之IPC连接 以及 python生成exe可执行程序讲解方式方法
  • 「Mac畅玩鸿蒙与硬件7」鸿蒙开发环境配置篇7 - 使用命令行工具和本地模拟器管理项目
  • Spring Boot 安全 API 构建:加密解密功能的卓越实践
  • Linux 上安装 conda 步骤实现
  • 一、ARMv8寄存器之通用、状态、特殊寄存器
  • String常量池
  • 【秋招笔试-支持在线评测】10.30花子秋招(已改编)-三语言题解
  • Codeforces Global Round 27 D.Yet Another Real Number Problem
  • 双11来了,云计算优惠大集合
  • android 10 后台启动activity
  • Unity Editor 快速移动资源
  • VB中如何创建和使用自定义控件