Linux系统编程:多线程交替打印ABC

2023-11-19

引言

分享关于线程的一道测试题,因为网上基本都是Java的解决方法,决定自己写一篇来记录一下线程的学习。

问题描述

编写一个至少具有三个线程的程序(称之为线程 A、B 和 C),其中线程 A 输出字符’A’,线程 B 输出字符’B’,线程 C 输出字符’C’。使得最终输出结果为“ABCABCABC…”。

思路

拿到这题后,我的想法是把问题简化
原题让我们交替打印ABC,那么我们只要先考虑如何交替打印AB即可,然后在B之后衔接C,在C之后衔接A即可。

那么,如何使两个线程能够按照顺序去执行任务呢?
关于线程同步,首先我们想到的是互斥锁mutex。
但是mutex的缺点很明显,只有简单的拿锁和解锁两个状态,并且你无法保证谁先拿锁,也就是说你没法保证两个线程按照顺序去执行任务。
在Linux中,为了配合互斥锁mutex的使用,引入了条件变量cond。
它允许一个线程阻塞,直到另一个线程唤醒它。因此,我们可以想到用cond来实现顺序,解出题目。

具体的思路是:
设置三个不同的条件变量,分别代表前置线程是否结束任务时间(这样才能一环套一环才能保证线程按照顺序打印呀);配套这些条件变量的是三个互斥锁,分别代表哪个线程处于任务时间。
例如说,负责打印A的线程A的先等待标志线程C已经结束任务的条件变量唤醒,我们命名为c_over,来表示线程C已经结束任务。线程C结束任务后,轮到线程A工作了,此时线程A拿锁,同样的我们把这把锁命名为a_time,表示是线程A的工作时间,此时线程B和线程C都不会工作。最后,线程A打印出字符A后,释放这把a_time,表示线程A结束任务,同时通过a_over唤醒线程B。

注意点

一、
如果所有线程都像上述这么做,也就是所有线程都等待条件变量唤醒而阻塞着,没法工作。

解决方案
在主线程中唤醒线程A

二、
若在主线程中直接使用return 0退出,内核会回收掉整个进程的资源,结束其余线程的任务。

解决方案
在主线程中调用pthread_exit()或是在最后加上一行while (1);

代码

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <pthread.h>

pthread_mutex_t a_time, b_time, c_time; 
pthread_cond_t a_over = PTHREAD_COND_INITIALIZER;
pthread_cond_t b_over = PTHREAD_COND_INITIALIZER;
pthread_cond_t c_over = PTHREAD_COND_INITIALIZER;

void my_err(const char *str)
{
     perror(str);
     exit(1);
}

void *func_a(void *arg)
{
    while (1)
    {
        pthread_mutex_lock(&a_time);
        pthread_cond_wait(&c_over, &a_time);
        putchar('A');
        pthread_mutex_unlock(&a_time);
        pthread_cond_signal(&a_over);
    }
}

void *func_b(void *arg)
{
    while (1)
    {
        pthread_mutex_lock(&b_time);
        pthread_cond_wait(&a_over, &b_time);
        putchar('B');
        pthread_mutex_unlock(&b_time);
        pthread_cond_signal(&b_over);
    }
}

void *func_c(void *arg)
{
    while (1)
    {
        pthread_mutex_lock(&c_time);
        pthread_cond_wait(&b_over, &c_time);
        putchar('C');
        pthread_mutex_unlock(&c_time);
        pthread_cond_signal(&c_over);
    }
}

int main(int argc, char *argv[])
{
    pthread_t tid_a, tid_b, tid_c;
    pthread_mutex_init(&a_time, NULL);
    pthread_mutex_init(&b_time, NULL);
    pthread_mutex_init(&c_time, NULL);
    pthread_create(&tid_a, NULL, func_a, NULL);
    pthread_create(&tid_b, NULL, func_b, NULL);
    pthread_create(&tid_c, NULL, func_c, NULL);
    pthread_cond_signal(&c_over);
    pthread_exit( (void*)0 );   //while (1);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux系统编程:多线程交替打印ABC 的相关文章

  • ioctl 命令的用户权限检查

    我正在实现 char 驱动程序 Linux 并且我的驱动程序中有某些 IOCTL 命令仅需要由 ADMIN 执行 我的问题是如何在 ioctl 命令实现下检查用户权限并限制非特权用户访问 IOCTL 您可以使用bool capable in
  • 相当于Linux中的导入库

    在 Windows C 中 当您想要链接 DLL 时 您必须提供导入库 但是在 GNU 构建系统中 当您想要链接 so 文件 相当于 dll 时 您就不需要链接 为什么是这样 是否有等效的 Windows 导入库 注意 我不会谈论在 Win
  • 通过 Visual Studio 2017 使用远程调试时 Linux 控制台输出在哪里?

    我的Visual Studio 2017 VS2017 成功连接Linux系统 代码如下 include
  • Linux 上的静态 Qt5 构建:部署时如何处理字体?

    我使用这些配置选项创建了 Qt 5 2 0 库的静态版本 Ubuntu 12 04 开源 确认许可 force pkg config 发布 静止的 前缀 home juzzlin qt5 无icu opengl桌面 无油嘴滑舌 辅助功能 n
  • 就分页分段内存而言的程序寿命

    我对 x86 Linux 机器中的分段和分页过程有一个令人困惑的概念 如果有人能澄清从开始到结束所涉及的所有步骤 我们将很高兴 x86 使用分页分段内存技术进行内存管理 任何人都可以解释一下从可执行的 elf 格式文件从硬盘加载到主内存到它
  • 添加文件时运行 shell 命令

    我的 Linux 机器上有一个名为 images 的文件夹 该文件夹连接到一个网站 该网站的管理员可以向该网站添加图片 但是 当添加图片时 我想要一个命令来运行调整目录中所有图片的大小 简而言之 我想知道当新文件添加到特定位置时如何使服务器
  • 为什么 fopen("any_path_name",'r') 不给出 NULL 作为返回值?

    在调试一些代码时 我得到如下内容 include
  • 并行运行 shell 脚本

    我有一个 shell 脚本 打乱大型文本文件 600 万行和 6 列 根据第一列对文件进行排序 输出 1000 个文件 所以伪代码看起来像这样 file1 sh bin bash for i in seq 1 1000 do Generat
  • CMake 链接 glfw3 lib 错误

    我正在使用 CLion 并且正在使用 glfw3 库编写一个程序 http www glfw org docs latest http www glfw org docs latest 我安装并正确执行了库中的所有操作 我有 a 和 h 文
  • 使用 shell 脚本将行附加到 /etc/hosts 文件

    我有一个新的 Ubuntu 12 04 VPS 我正在尝试编写一个安装脚本来完成整个 LAMP 安装 我遇到问题的地方是在 etc hosts文件 我当前的主机文件如下所示 127 0 0 1 localhost Venus The fol
  • 使用包管理器时如何管理 Perl 模块?

    A 最近的问题 https stackoverflow com questions 397817 unable to find perl modules in intrepid ibex ubuntu这让我开始思考 在我尝试过的大多数 Li
  • 静态方法的 Java 内存模型

    我来自操作系统和 C 语言背景 在代码编译时 世界很简单 需要处理和理解堆栈 堆文本部分等 当我开始学习 Java 时 我确实了解 JVM 和垃圾收集器 我对静态方法感到很有趣 根据我的理解 类的所有实例都会在堆中创建 然后被清理 但是 对
  • 如何在 Linux 中使用 C 语言使用共享内存

    我的一个项目有点问题 我一直在试图找到一个有据可查的使用共享内存的例子fork 但没有成功 基本上情况是 当用户启动程序时 我需要在共享内存中存储两个值 当前路径这是一个char and a 文件名这也是char 根据命令参数 启动一个新进
  • Intel 上的 gcc 中的 _mm_pause 用法

    我参考过这个网页 https software intel com en us articles benefitting power and performance sleep loops https software intel com
  • C修改printf()输出到文件

    有没有办法修改printf为了将字符串输出到文件而不是控制台 我尝试在互联网上查找一些内容 发现了类似的电话dup dup2 and fflush这可能与此有关 EDIT 也许我不清楚 问题是这是C考试问题 问题如下 解释一个通常将字符串输
  • 为什么opencv videowriter这么慢?

    你好 stackoverflow 社区 我有一个棘手的问题 我需要你的帮助来了解这里发生了什么 我的程序从视频采集卡 Blackmagic 捕获帧 到目前为止 它工作得很好 同时我用 opencv cv imshow 显示捕获的图像 它也工
  • 使用 python 脚本更改 shell 中的工作目录

    我想实现一个用户态命令 它将采用其参数之一 路径 并将目录更改为该目录 程序完成后 我希望 shell 位于该目录中 所以我想实施cd命令 但需要外部程序 可以在 python 脚本中完成还是我必须编写 bash 包装器 Example t
  • 使用os.execlp时,为什么`python`需要`python`作为argv[0]

    代码是这样的 os execlp python python child py other args this works os execlp python child py other args this doesn t work 我读过
  • 复制目录内容

    我想将目录 tmp1 的内容复制到另一个目录 tmp2 tmp1 可能包含文件和其他目录 我想使用C C 复制tmp1的内容 包括模式 如果 tmp1 包含目录树 我想递归复制它们 最简单的解决方案是什么 我找到了一个解决方案来打开目录并读
  • ansible unarchive 模块如何查找 tar 二进制文件?

    我正在尝试执行一个 ansible 剧本 该剧本的任务是利用unarchive模块 因为我是在 OSX 上执行此操作 所以我需要使用它gnu tar 而不是bsd tar通常与 OSX 一起提供 因为BSD tar 不受官方支持 https

随机推荐

  • MySql导出表结构到Word文档

    工具比较简陋 因工作要求临时写的 功能单一 只为了导出mysql表结构到word文档 运行环境 jdk1 8 执行命令 java jar xxxx jar 缺点 暂时只支持导出MySQL数据库 输入数据库配置和文件导出路径后点击测试连接 点
  • 正在启动文档服务器,正在启动远程服务器

    正在启动远程服务器 内容精选 换一换 本节操作介绍云服务器新内核启动失败时如何设置使用第二内核启动 本节操作适用于CentOS EulerOS操作系统 且系统内安装至少两个内核 登录控制台 重启云服务器 单击 远程登录 在出现Booting
  • 计算机win7几位,Win7 32位与64位有什么区别 Win7系统32位和64位的区别科普篇

    Win7系统分32位和64位版本 很多人在选择32位和64位系统的时候十分纠结 原因是自己的电脑应该安装哪一种版本 那么Win7 32位与64位有什么区别 下面装机之家分享一下Win7系统32位和64位的区别科普篇 Win7系统32位和64
  • 查看apk签名,查看key签名,adb常用命令

    在使用第三方sdk时经常要求绑定签名 这里提供两种查看签名的方式 如果只是想查看一下手机上应用的签名 那么可以安装一个app直接输入包名即可查看该应用的签名 提供一个微信的签名查看apk 下载连接http download csdn net
  • 【认证证书】计算机应急响应 - 中国信息安全测评中心CISP-IRE

    计算机应急响应 中国信息安全测评中心CISP IRE 知识体系 简略图片版 详细 官方 中国信息安全测评中心 http www itsec gov cn ryzc rsqsxz 版 考核方式 公安部第三研究所CCSS R 考核方式 资料 题
  • 使用wget从Google Drive下载数据集

    许多用于训练的数据集很大 一般通过Google Drive进行分享 而出于磁盘容量和方便训练的考虑 这些数据我们一般放在服务器上 服务器没有图形界面 因此我们需要使用wget来进行下载 Google Drive的链接格式是这个样子的 htt
  • go语言教程哪里有?go 语言优秀开源项目汇总

    目录 监控系统 容器技术 PaaS工具 大数据 微服务 CI CD 数据库技术 存储技术 分布式系统 消息系统 服务器管理 安全工具 网络工具 Web工具 Web框架 区块链技术 其它 监控系统 项目 简介 OpenFalcon OpenF
  • python:转义字符和input()的用法

    1 1转义字符 1序列 表反斜杆 表单引号 表双引号 a表ASCLL响铃符 BEL b表ASCLL退格符 BS f表ASCLL进纸符 FF n表ASCLL换行符 LF N name 表Udicode数据库中的字符名 其中name时它的名字
  • python 使用 openpyxl 打开及读取 excel 表格

    python 使用 openpyxl 打开及读取 excel 表格 openpyxl简介 安装openpyxl 打开及读取表格内容 1 打开 Excel 表格并获取表格名称 2 通过 sheet 名称获取表格 3 获取表格的尺寸大小 几行几
  • Spring创建Bean实例的方式

    目录 简介 源码分析 resolveBeforeInstantiation创建Bean实例 doCreateBean创建Bean实例 Supplier创建实例 FactoryMethod创建实例 自动装配构造函数创建实例 无参构造函数创建实
  • nslookup命令详解

    nslookup命令用于查询DNS的记录 查看域名解析是否正常 在网络故障的时候用来诊断网络问题 nslookup的用法相对来说还是蛮简单的 主要是下面的几个用法 1 直接查询 这个可能大家用到最多 查询一个域名的A记录 nslookup
  • 解决Proteus仿真时候提示Could not load simulator DLL错误

    之前在进行Proteus仿真时候 弹出来三个错误 分别是 1 Could not load simulator DLL E Program Files x86 BIN PROSPICE DLL 2 Could not find or run
  • 二阶电路的零状态响应

    二阶电路零状态响应公式推导 下图所示电路在 时电容和电感上储能都为零 即 t 0 时开关闭合 电压源 Us 开始对电路供电 现讨论 时响应的变化规律 电路的 KVL 方程为换路后电路的初始状态为 0 即 这是二阶线性非齐次微分方程 它的解由
  • vue中点击第一次没有触发按钮怎么操作_vue如何触发某个元素的单击事件?

    我来回答一波吧 因为没复习 导致知识点结合不紧密 原生的中 我们的写法是这样的 王蒿大爷 function myFunction document getElementById demo innerHTML Hello World wind
  • 程序员简历应该怎么写?

    说到程序员简历 这两个月 我看过不下10 000份简历 答主不是HR 也不是技术负责人 但是在网站的运营工作中 每天最开心的事情就是研究候选人的简历了 这些人中 有BAT的资深大牛程序员 也有90后程序员小鲜肉 有人到中年的程序员渴望去创业
  • MyBatis参数传入集合之foreach动态sql

    foreach的主要用在构建in条件中 它可以在SQL语句中进行迭代一个集合 foreach元素的属性主要有item index collection open separator close item表示集合中每一个元素进行迭代时的别名
  • 期货反向跟单--交易员的培养问题

    根据我们统计的数据显示 今年做国内期货反向跟单的团队 无论是从赢利金额 稳定性 还是成功概率 都比做国际期货的团队要高 尤其是最近纯碱 焦煤焦炭 PTA 红枣等几个品种的行情 更是频繁拉爆了很多盘手的账户 本文转发自公众号 反跟单交易 转载
  • 【Mysql】Communications link failure,The last packet sent successfully to the server was 0 millisecond

    项目背景是数据库和项目不在同一台服务器下 在启动时 突然遇到以下错误 Exception in thread main com mysql jdbc exceptions jdbc4 CommunicationsException Comm
  • Java图书馆

    io流用的不是很熟练 还有Book类的应用出了点问题 越改越错 从2个错误改到102个QAQ 孩子想哭 问了好多人也没改成 最后勉强成型 而且上个星期内分泌系统出了点小问题 天天往医院跑 开始敲的太晚了 现在要备战期末考 等期末考结束再改改
  • Linux系统编程:多线程交替打印ABC

    引言 分享关于线程的一道测试题 因为网上基本都是Java的解决方法 决定自己写一篇来记录一下线程的学习 问题描述 编写一个至少具有三个线程的程序 称之为线程 A B 和 C 其中线程 A 输出字符 A 线程 B 输出字符 B 线程 C 输出