线程学习--pthread--锁链及条件变量

2023-11-08

pthread_cond_wait函数的使用,一般跟lock一起用

pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);
  1. 等待条件变量满足;
  2. 把获得的锁释放掉;(注意:1,2两步是一个原子操作) 当然如果条件满足了,那么就不需要释放锁。所以释放锁这一步和等待条件满足一定是一起执行(指原子操作)。--很重要。
  3. pthread_cond_wait()被唤醒时,它解除阻塞,并且尝试获取锁(不一定拿到锁)。因此,一般在使用的时候都是在一个循环里使用pthread_cond_wait()函数,因为它在返回的时候不一定能拿到锁(这可能会发生饿死情形,当然这取决于操作系统的调度策略)。

首先加锁pthread_mutex_lock(),等待条件变量的到来,通常在一个while循环中使用,条件变量唤醒,不满足条件,解锁继续等待下一次条件变量的到来。

需求创建4个线程,每一个线程打印一个字符,按顺序打印abcd

第一版--锁链,不建议使用这种方法,可能会产生未定义行为

原理:创建四个线程,四把锁,第一线程解下一个线程的锁(不同的线程解同一把会产生未定义行为)

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

#define NUM 4
pthread_mutex_t mutex[NUM];

int next(int i)
{
    if(i == 3)
        return 0;
    return i+1;
}

void *handler(void *p)
{
    int i = *(int*)p;
    while(1)
    {
        pthread_mutex_lock(mutex+i);
        printf("%d",i+1);
        pthread_mutex_unlock(mutex+next(i));
    }

    pthread_exit(p);
}

int main()
{
    int i = 0;
    pthread_t tid[NUM];
    void *ptr = NULL;
    for(; i < NUM; i++)
    {
        int *num = malloc(sizeof(int));
        *num = i;
        //mutex[i] = PTHREAD_MUTEX_INITIALIZER;//PTHREAD_MUTEX_INITIALIZER
        pthread_mutex_init(mutex+i, NULL);
        pthread_mutex_lock(mutex+i);
        if(pthread_create(tid+i, NULL, handler, (void*)num))
        {
            perror("pthread_create()");
            exit(-1);
        }
    }
    pthread_mutex_unlock(mutex);

    alarm(1);

    for(i = 0; i < NUM; i++)
    {
        pthread_join(tid[i], ptr);
        free(ptr);
    }
    
    exit(0);
}

第二种方法:使用条件变量

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#define NUM 4
pthread_mutex_t mutex;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static int num = 0;
static int next(int i)
{
    if(i == 3)
        return 0;
    return i+1;
}
static void *handler(void *p)
{
    int i = *(int*)p;
    while(1)
    {
        pthread_mutex_lock(&mutex);//注释掉的锁挪到这里就可以了。
        while(num != i)
            pthread_cond_wait(&cond, &mutex);
        //之前把锁放在这里,产生了死锁,一直搞不懂,
        //1.应先加锁,再查看num值
        //2.pthread_cond_wait是等待条件变量的到来,如果到来,拿到锁,然后释放锁。
        //pthread_mutex_lock(&mutex);
        printf("%d", num);
        num = next(num);
        pthread_cond_broadcast(&cond);
        pthread_mutex_unlock(&mutex);
    }
    pthread_exit(p);
}
int main()
{
    int i = 0;
    pthread_t tid[NUM];
    void *ptr = NULL;
    pthread_mutex_init(&mutex, NULL);
    pthread_mutex_lock(&mutex);
    for(; i < NUM; i++)
    {
        int *num = malloc(sizeof(int));
        *num = i;
        if(pthread_create(tid+i, NULL, handler, (void*)num))
        {
            perror("pthread_create()");
            exit(-1);
        }
    }
    pthread_cond_broadcast(&cond);
    pthread_mutex_unlock(&mutex);
    alarm(1);
    for(i = 0; i < NUM; i++)
    {
        pthread_join(tid[i], ptr);
        free(ptr);
    }
    exit(0);
}

更简洁条件变量版:不在主线程中加锁

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

#define NUM 4
pthread_mutex_t mutex;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

static int num = 0;

static int next(int i)
{
    if(i == 3)
        return 0;
    return i+1;
}

static void *handler(void *p)
{
    int i = (int)p;
    while(1)
    {
        pthread_mutex_lock(&mutex);
        while(num != i)
            pthread_cond_wait(&cond, &mutex);
        num = next(num);
        printf("%d", num);
        pthread_cond_broadcast(&cond);
        pthread_mutex_unlock(&mutex);
    }
    pthread_exit(p);
}

int main()
{

    int i = 0;
    pthread_t tid[NUM];
    void *ptr = NULL;
    
    pthread_mutex_init(&mutex, NULL);
    for(; i < NUM; i++)
    {
        if(pthread_create(tid+i, NULL, handler, (void*)i))
        {
            perror("pthread_create()");

            exit(-1);
        }
    }

    alarm(2);

    for(i = 0; i < NUM; i++)
    {
        pthread_join(tid[i], ptr);
        free(ptr);
    }
    
    exit(0);
}

--李慧琴老师课程笔记

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

线程学习--pthread--锁链及条件变量 的相关文章

  • 02梯度下降

    参考 http biranda top Pytorch学习笔记004 梯度下降算法 随机梯度下降 补充 五折交叉验证 如下右图 在不同的训练集和测试集划分方法下 test MSE的变动是很大的 而且对应的最优degree也不一样 所以如果我

随机推荐

  • 链游开发 链游游戏开发

    链游就是指区块链技术上运作的手机游戏 使游戏玩家第一次变成手机游戏真正的主人 游戏玩家在游戏里面所具备的的武器装备是可以随意交易的NFT 不会受到游戏开发商的操纵 别的游戏开发商可以对于游戏玩家的NFT搭建新的游戏 假如之前的游戏软件开发得
  • MySQL中的DDL常规操作总结

    MySQL中的DDL常规操作总结 相信对于一个后端开发人员来说 SQL的DML Data Manipulation Language 操作是很熟悉的 毕竟在忙于写业务代码的同时 对数据操作最多的就是增加 Create 检索 Retrieve
  • 浏览器汇总、可信浏览器

    文章目录 1 浏览器引擎分类 2 浏览器组成 3 内核 4 浏览器中的进程与线程 6 页面渲染流程 7 回流与重绘 重排 重绘 8 优化渲染性能 9 输入URL地址 浏览器经历了什么 真实dom树生成及解析流程 10 浏览器访问网页 第一次
  • 关注 OpenStack 的筒子们,福利来啦!

    2017 OpenStack Days China 将于 2017 年 7 月 24 日 25 日 周一至周二 在北京国家会议中心隆重召开 我们非常荣幸能和大家一起见证并打造这样一个强有力的 大规模的云计算标准软件平台 这一次 OpenSt
  • 如何在MarkDown文件中插入Emoji表情?

    如何在MarkDown文件中插入Emoji表情 解决方法 markdown语法的目的是使用户专注于文本内容编辑 在双手不离开键盘的情况下也能对页面进行排版编辑 提高内容书写的效率和可读性 如果在文档中添加一些符号表情 也能为文本增添一些趣味
  • 如何通过JDBC连接远程服务端的数据库

    如何通过JDBC连接远程服务端的数据库 1 本地navicat链接到远程服务端 2 Myeclipse创建JDBC 1 本地navicat链接到远程服务端 首先 打开远程服务器 远程数据库中新建查询 输入SQL语句 表示允许任何主机访问数据
  • 【Uniapp】一、 UniAPP框架基本信息

    1 什么是 UniAPP uni app 是一个使用 Vue js 开发所有前端应用的框架 开发者编写一套代码 可发布到 iOS Android H5 以及各种小程序 微信 支付宝 百度 头条 QQ 钉钉 等多个平台 uni app在手 做
  • 【实际开发21】- 项目部署

    目录 1 项目打包方式就两种 war jar 1 Windows 环境运行 Jar 包 2 Windows 后台运行 jar 包 1 cmd 下执行方式 2 bat 批处理方式 Batch 3 启动 在 xx jar 同级目录下建立 run
  • 114.114.114.114和8.8.8.8两者联系与区别

    联系 114 114 114 114 和 8 8 8 8 这两个IP地址都属于公共域名解析服务DNS其中的一部分 而且由于不是用于商业用途的 这两个DNS都很纯净 不用担心因ISP运营商导致的DNS劫持等问题 而且都是免费提供给用户使用的
  • 【编程笔试】美团2021校招笔试-通用编程题第8场(附思路及C++代码)

    导览 练习地址 小美的书架 偏爱字母 搭配出售 十字路口 练习地址 点此前往练习 小美的书架 小美的书架上有很多书 小美是个爱读书的新时代好青年 小团虽然也喜欢看书 但小团大多数时候都更喜欢来小美家蹭书读 这就导致小美的书架上很多书都会被小
  • 区块链-为什么区块链是不可篡改的

    目录 https blog csdn net qq 40452317 article details 89646633 区块链的数据结构是由包含交易信息的区块按照从远及近的顺序有序链接起来的 区块被从远及近有序地链接在这个链条里 每个区块都
  • python 多元回归参数输出_python-如何从statsmodels中的WLS回归的2D参数获...

    我使用statsmodels递增了WLS regression functions的参数 我有一个这样声明的10 3数据集X X np array 1 2 3 1 2 3 4 5 6 1 2 3 4 5 6 1 2 3 1 2 3 4 5
  • HTML学习篇

    基于HBuild 综合训练1 img src img 666 jpg title width 200 height 300 border 5 br a href work1 跳转锚点 a a href class1 html target
  • Spring Cache缓存技术的介绍

    缓存用于提升系统的性能 特别适用于一些对资源需求比较高的操作 本文介绍如何基于spring boot cache技术 使用caffeine作为具体的缓存实现 对操作的结果进行缓存 demo场景 本demo将创建一个web应用 提供两个Res
  • 科大讯飞版ChatGPT提前内测!附申请方法

    讯飞 星火 认知大模型是科大讯飞版的 ChatGPT 在内测阶段 目前已经开放内测申请 它可以学习和理解人类语言 进行多轮对话 回答问题并帮助人们快速获取知识和灵感 可用于写作诗歌 歌词 故事 代码和表格等 并能够分析逻辑问题 解决数学题及
  • 【Bootstrap】Bootstrap添加时间选择器组件datetimepicker

    文章目录 Bootstrap Bootstrap添加时间选择器组件datetimepicker 一 引入bootstrap基础库 二 引入bootstrap datetimepicker库 三 使用方法 四 一些问题 Bootstrap B
  • 企业为什么要上云?企业上云的好处和优势有哪些

    企业上云是比较热门的话题也是趋势 越来越多的企业放弃传统IDC选择上云 新手站长网告诉你企业为什么要上云 企业上云的好处和优势有哪些 企业为什么要上云 企业上云也是企业集成发展的趋势 国内外很多企业相继投入了云的怀抱 诸如飞利浦关闭中国数据
  • 大数据毕设项目 机器学习餐厅销量预测 -大数据 python

    文章目录 0 前言 餐厅销量预测 一 建模流程 二 模型简介 2 ARIMA模型介绍 2 1自回归模型AR 2 2移动平均模型MA 2 3自回归移动平均模型ARMA 三 模型识别 四 模型检验 4 1半稳性检验 1 用途 1 什么是平稳序列
  • uni-app中小数变成整数,开方

    保留整数部分 会转化成1 parseInt 1 6 舍去小数部分 会转化成1 Math floor 1 6 小数部分进位 会转化成2 Math ceil 1 6 四舍五入 1 6 gt 2 1 4 gt 1 Math round 1 6 3
  • 线程学习--pthread--锁链及条件变量

    pthread cond wait函数的使用 一般跟lock一起用 pthread mutex lock mutex pthread cond wait cond mutex 等待条件变量满足 把获得的锁释放掉 注意 1 2两步是一个原子操