用解释程序交错执行2个线程

多线程问题,对初学者来说,会常常感到神秘。特别想知道它里面到底是怎么执行的;遇到问题时,又会觉得十分迷惑。

前面的例子,swap 语句串扰执行问题,实现了一个assign指令的解释器。现在就借用它的代码,用解释程序演示一下多线程是怎么执行的。

现在注意力集中到考虑,以swap(a,b):, swap(a,c):, 为蓝本的2个线程,每个线程各执行相应的swap代码10次。线程的数据结构是:

struct thread_proc {
        int ecount;
        int count;
        struct assign **ins;
        int n;
        int cur;
};

其中,用ecount表示thread的任务是执行10次,count从 0计数,到ecount执行结束。ins照旧,存放swap(a,b):或swap(a,c):的指令。n是指令的长度。cur是thread当前执行到的位置。

线程初始化为各执行swap(a,b):或swap(a,c):10次:

struct assign *swap_ab_ins[3]= {
        &all_assigns[0], &all_assigns[1], &all_assigns[2]
};
struct assign *swap_ac_ins[3]= {
        &all_assigns[3], &all_assigns[4], &all_assigns[5]
};
struct thread_proc thread2[2]=
{
        {10, 0, swap_ab_ins, 3, 0},
        {10, 0, swap_ac_ins, 3, 0},
};

线程执行,每个片断执行1~3个线程指令:

void execute(struct thread_proc *t, int n)
{
        int i;
        int pos;
        struct assign **a;
        a = t->ins;
        if(t==&thread2[0]) {
                printf("swap(a,b):");
        }
        else {
                printf("swap(a,c):");
        }

        for(i=0; i<n; i++) {
                if(i) printf("\t");
                pos = t->cur;
                print_ins_nl(a[pos], 0);
                *(a[pos]->left) = *(a[pos]->right);
                printf("\t");
                print_vars(&result); printf("\n");
                t->cur++;
                if(t->cur>=t->n) {
                        t->count++;
                        t->cur=0;
                }
                if(finish(t)) break;
        }
}

调度程序,选择"下一个"需要执行的线程,交错执行每个线程:

struct thread_proc *run;
int finish(struct thread_proc *t)
{
        return t->count>=t->ecount;
}

int sched()
{
        struct thread_proc *next;
        if(run== &thread2[0]) {
                next= &thread2[1];
        } else {
                next= &thread2[0];
        }
        if(!finish(next)) {
                run= next;
        }
        if(!finish(run)) return 1;
        return 0;
}

当sched()选择的"下一个"线程已经finish,sched()就返回0。执行就结束了。就这些了。完整的代码贴上:

#include <stdio.h>

struct vars {
        int a;
        int b;
        int c;
        int t1;
        int t2;
};

struct vars init= {'A', 'B', 'C', 'x', 'z'};
struct vars result;

struct assign {
        int *left;
        int *right;
};

struct assign all_assigns[] = {
        {&result.t1,&result.a}, {&result.a, &result.b}, {&result.b,&result.t1},
        {&result.t2,&result.a}, {&result.a, &result.c}, {&result.c,&result.t2},
};


void print_ins_nl(struct assign *a, int nl)
{
        int i;
        int *pi= a->left;
        printf("\t(%d)\t", a- &all_assigns[0]);
        for(i=0; i<2; i++) {
                if(pi==&result.a) printf("a"); else
                if(pi==&result.b) printf("b"); else
                if(pi==&result.c) printf("c"); else
                if(pi==&result.t1) printf("t1"); else
                if(pi==&result.t2) printf("t2");
                if(pi==a->left) {
                        printf("=");
                        pi=a->right;
                }
        }
        if(nl)
        printf(";\n");
        else
        printf(";");
}

void print_ins(struct assign *a)
{
        print_ins_nl(a, 1);
}


void print_vars(struct vars *var)
{
        printf("(%c, %c, %c, :%c, :%c)", var->a, var->b,var->c, var->t1, var->t2
);
}


struct thread_proc {
        int ecount;
        int count;
        struct assign **ins;
        int n;
        int cur;
};

struct assign *swap_ab_ins[3]= {
        &all_assigns[0], &all_assigns[1], &all_assigns[2]
};
struct assign *swap_ac_ins[3]= {
        &all_assigns[3], &all_assigns[4], &all_assigns[5]
};
struct thread_proc thread2[2]=
{
        {10, 0, swap_ab_ins, 3, 0},
        {10, 0, swap_ac_ins, 3, 0},
};

struct thread_proc *run;
int finish(struct thread_proc *t)
{
        return t->count>=t->ecount;
}

int sched()
{
        struct thread_proc *next;
        if(run== &thread2[0]) {
                next= &thread2[1];
        } else {
                next= &thread2[0];
        }
        if(!finish(next)) {
                run= next;
        }
        if(!finish(run)) return 1;
        return 0;
}

void execute(struct thread_proc *t, int n)
{
        int i;
        int pos;
        struct assign **a;
        a = t->ins;
        if(t==&thread2[0]) {
                printf("swap(a,b):");
        }
        else {
                printf("swap(a,c):");
        }

        for(i=0; i<n; i++) {
                if(i) printf("\t");
                pos = t->cur;
                print_ins_nl(a[pos], 0);
                *(a[pos]->left) = *(a[pos]->right);
                printf("\t");
                print_vars(&result); printf("\n");
                t->cur++;
                if(t->cur>=t->n) {
                        t->count++;
                        t->cur=0;
                }
                if(finish(t)) break;
        }
}

extern "C" int rand();
int random()
{
        return rand()%3+1;
}

int main()
{
        int i;
        printf("swap(a, b):\n");
        for(i=0; i<3; i++) {
                print_ins(&all_assigns[i]);
        }
        printf("swap(a, c):\n");
        for(i=0; i<3; i++) {
                print_ins(&all_assigns[i+3]);
        }
        printf("[execute]:\n");
        result = init;
        run = &thread2[0];
        do {
                execute(run, random());
        }
        while(sched());
        return 0;
}

运行结果是交错执行2个线程的效果:

swap(a, b):
        (0)     t1=a;
        (1)     a=b;
        (2)     b=t1;
swap(a, c):
        (3)     t2=a;
        (4)     a=c;
        (5)     c=t2;
[execute]:
swap(a,b):      (0)     t1=a;   (A, B, C, :A, :z)
swap(a,c):      (3)     t2=a;   (A, B, C, :A, :A)
                (4)     a=c;    (C, B, C, :A, :A)
                (5)     c=t2;   (C, B, A, :A, :A)
swap(a,b):      (1)     a=b;    (B, B, A, :A, :A)
swap(a,c):      (3)     t2=a;   (B, B, A, :A, :B)
                (4)     a=c;    (A, B, A, :A, :B)
                (5)     c=t2;   (A, B, B, :A, :B)
swap(a,b):      (2)     b=t1;   (A, A, B, :A, :B)
                (0)     t1=a;   (A, A, B, :A, :B)
                (1)     a=b;    (A, A, B, :A, :B)
swap(a,c):      (3)     t2=a;   (A, A, B, :A, :A)
swap(a,b):      (2)     b=t1;   (A, A, B, :A, :A)
swap(a,c):      (4)     a=c;    (B, A, B, :A, :A)
                (5)     c=t2;   (B, A, A, :A, :A)
swap(a,b):      (0)     t1=a;   (B, A, A, :B, :A)
swap(a,c):      (3)     t2=a;   (B, A, A, :B, :B)
                (4)     a=c;    (A, A, A, :B, :B)
                (5)     c=t2;   (A, A, B, :B, :B)
swap(a,b):      (1)     a=b;    (A, A, B, :B, :B)
                (2)     b=t1;   (A, B, B, :B, :B)
swap(a,c):      (3)     t2=a;   (A, B, B, :B, :A)
swap(a,b):      (0)     t1=a;   (A, B, B, :A, :A)
                (1)     a=b;    (B, B, B, :A, :A)
                (2)     b=t1;   (B, A, B, :A, :A)
swap(a,c):      (4)     a=c;    (B, A, B, :A, :A)
swap(a,b):      (0)     t1=a;   (B, A, B, :B, :A)
                (1)     a=b;    (A, A, B, :B, :A)
                (2)     b=t1;   (A, B, B, :B, :A)
swap(a,c):      (5)     c=t2;   (A, B, A, :B, :A)
swap(a,b):      (0)     t1=a;   (A, B, A, :A, :A)
                (1)     a=b;    (B, B, A, :A, :A)
                (2)     b=t1;   (B, A, A, :A, :A)
swap(a,c):      (3)     t2=a;   (B, A, A, :A, :B)
swap(a,b):      (0)     t1=a;   (B, A, A, :B, :B)
swap(a,c):      (4)     a=c;    (A, A, A, :B, :B)
                (5)     c=t2;   (A, A, B, :B, :B)
                (3)     t2=a;   (A, A, B, :B, :A)
swap(a,b):      (1)     a=b;    (A, A, B, :B, :A)
                (2)     b=t1;   (A, B, B, :B, :A)
                (0)     t1=a;   (A, B, B, :A, :A)
swap(a,c):      (4)     a=c;    (B, B, B, :A, :A)
                (5)     c=t2;   (B, B, A, :A, :A)
swap(a,b):      (1)     a=b;    (B, B, A, :A, :A)
                (2)     b=t1;   (B, A, A, :A, :A)
                (0)     t1=a;   (B, A, A, :B, :A)
swap(a,c):      (3)     t2=a;   (B, A, A, :B, :B)
                (4)     a=c;    (A, A, A, :B, :B)
                (5)     c=t2;   (A, A, B, :B, :B)
swap(a,b):      (1)     a=b;    (A, A, B, :B, :B)
                (2)     b=t1;   (A, B, B, :B, :B)
                (0)     t1=a;   (A, B, B, :A, :B)
swap(a,c):      (3)     t2=a;   (A, B, B, :A, :A)
                (4)     a=c;    (B, B, B, :A, :A)
swap(a,b):      (1)     a=b;    (B, B, B, :A, :A)
                (2)     b=t1;   (B, A, B, :A, :A)
swap(a,c):      (5)     c=t2;   (B, A, A, :A, :A)
swap(a,c):      (3)     t2=a;   (B, A, A, :A, :B)
swap(a,c):      (4)     a=c;    (A, A, A, :A, :B)
swap(a,c):      (5)     c=t2;   (A, A, B, :A, :B)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/781121.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CountDownLatch内部原理解析

文章目录 1、CountDownLatch介绍1.1、功能介绍1.2、demo1.3、问题 2、前置知识2.1、AQS整体结构2.1.1、整体结构2.1.2、state属性2.1.3、head和tail属性 3、CountDownLatchAPI源码解析3.1、countDown方法3.1.1、Sync类3.1.2、releaseShared方法3.1.3、tryReleaseShared方法 3.2…

C++库函数--next_permutation(详细)

next_permutation介绍 用于生成某个序列的下一个排列。它通常在需要生成排列的问题中使用&#xff0c;比如全排列问题。 使用方法 普通序列 &#xff1a;next_permutation&#xff08;起始地址&#xff0c;末尾地址1&#xff09; 结构体&#xff1a;next_permutation&#…

解决 Layout Inspector无法查看Component Tree 布局层级信息 | Android Studio Koala

问题描述 Tool -> Layout Inspector 显示下图&#xff0c;无法生成.li文件查看Component Tree&#xff0c;变成实时的Preview并功能点击操作&#xff0c;跟模拟器一样。 原因&#xff1a;默认勾选了"Enable embedded Layout Inspector"&#xff0c;启用了嵌入式…

笔记本电脑内存不够

笔记本电脑内存不够是众多笔记本用户面临的常见问题&#xff0c;尤其是对于一些需要处理大型文件或者运行复杂软件的用户&#xff0c;这个问题可能会严重影响笔记本的使用体验。那么&#xff0c;我们应该如何解决笔记本电脑内存不够的问题呢&#xff1f;本文将从几个方面进行详…

flask使用定时任务flask_apscheduler(APScheduler)

Flask-APScheduler描述: Flask-APScheduler 是一个 Flask 扩展&#xff0c;增加了对 APScheduler 的支持。 APScheduler 有三个内置的调度系统可供您使用&#xff1a; Cron 式调度&#xff08;可选开始/结束时间&#xff09; 基于间隔的执行&#xff08;以偶数间隔运行作业…

RabbitMq - Java客户端基础【简单案例 +Work模型】

目录 1、前置知识 1.1、AMQP怎么理解 1.2、Spring AMQP是什么 1.3、为什么要了解Spring-AMQP&#xff1f; 2、使用Spring-AMQP实现一个发消息案例 3、Work模型 问题&#xff1a; 优化&#xff1a; 小结&#xff1a;Work模型的使用&#xff1a; 1、前置知识 1.1、AMQP怎…

[激光原理与应用-101]:南京科耐激光-激光焊接-焊中检测-智能制程监测系统IPM介绍 - 5 - 3C行业应用 - 电子布局类型

目录 前言&#xff1a; 一、激光在3C行业的应用概述 1.1 概述 1.2 激光焊接在3C-电子行业应用 二、3C电子行业中激光焊接 2.1 纽扣电池 2.2 均温板 2.3 指纹识别器 2.4 摄像头模组 2.5 IC芯片切割 三、3C行业中激光切割 四、激光在3C行业中的其他应用 4.1 涂层去除…

Towards Accurate and Robust Architectures via Neural Architecture Search

基于网络架构搜索的准确性与鲁棒性结构研究 论文链接&#xff1a;https://arxiv.org/abs/2405.05502 项目链接&#xff1a;未开源 Abstract 为了保护深度神经网络免受对抗性攻击&#xff0c;对抗性训练因其有效性而受到越来越多的关注。然而&#xff0c;对抗训练的准确性和鲁…

服务器本地部署文件服务器minio

minio类似于阿里云的OSS&#xff0c;为不方便把图、文、日志等形式的文件保存在公有云上的&#xff0c;可以在自己的服务器上部署文件服务器 看过本人前几个文章的&#xff0c;使用docker就会很快上手部署&#xff0c;直接上所有代码 #添加镜像 docker search minio docker p…

jvm 03 JVM的运行时数据区域 ,(类常量池,运行时常量池,字符串常量池这个三个的区别),操作系统内存模型JMM和JVM的内存模型联系

方法区在jdk8后&#xff0c;改成元空间 JVM内存模型&#xff1a; JMM 主内存&#xff1a;本地方法区和堆 工作内存&#xff1a;私有的工作栈 其实一个JVM内存模型&#xff08;主要就是运行时数据区域&#xff09;一个Java进程的JMM&#xff0c;工作内存JVM中线程的内存区域…

关于umjs的主题切换实现

注意本文写作日期2024年7月7日&#xff0c;我目前是最新版本的 注意&#xff1a;该功能仅 antd v5 可用 最后目标实现 先说一下&#xff0c;umijs布局默认是内置ant-design/pro-layout布局写的 看一下官网ProLayout - 高级布局和布局与菜单 直接在app.tsx加入以下&#xff…

Git管理源代码、git简介,工作区、暂存区和仓库区,git远程仓库github,创建远程仓库、配置SSH,克隆项目

学习目标 能够说出git的作用和管理源代码的特点能够如何创建git仓库并添加忽略文件能够使用add、commit、push、pull等命令实现源代码管理能够使用github远程仓库托管源代码能够说出代码冲突原因和解决办法能够说出 git 标签的作用能够使用使用git实现分支创建&#xff0c;合并…

磐维2.0数据库日常维护

磐维数据库简介 “中国移动磐维数据库”&#xff08;ChinaMobileDB&#xff09;&#xff0c;简称“磐维数据库”&#xff08;PanWeiDB&#xff09;。是中国移动信息技术中心首个基于中国本土开源数据库打造的面向ICT基础设施的自研数据库产品。 其产品内核能力基于华为 OpenG…

pyrender 离线渲染包安装教程

pyrender 离线渲染包安装教程 安装 安装 官方安装教程:https://pyrender.readthedocs.io/en/latest/install/index.html#installmesa 首先 pip install pyrenderclang6.0安装 下载地址:https://releases.llvm.org/download.html#6.0.0 注意下好是叫&#xff1a;clangllvm-6…

L04_MySQL知识图谱

这些知识点你都掌握了吗&#xff1f;大家可以对着问题看下自己掌握程度如何&#xff1f;对于没掌握的知识点&#xff0c;大家自行网上搜索&#xff0c;都会有对应答案&#xff0c;本文不做知识点详细说明&#xff0c;只做简要文字或图示引导。 1 基础 1.1内部组件结构 1.2 数据…

尚品汇-(十四)

&#xff08;1&#xff09;提交git 商品后台管理到此已经完成&#xff0c;我们可以把项目提交到公共的环境&#xff0c;原来使用svn&#xff0c;现在使用git 首先在本地创建ssh key&#xff1b; 命令&#xff1a;ssh-keygen -t rsa -C "your_emailyouremail.com" I…

用kimi实现一键实体识别与关系抽取

实体识别与关系抽取是自然语言处理&#xff08;NLP&#xff09;中的两个重要任务&#xff0c;通常被视为知识图谱构建的基础技术。 实体识别&#xff08;Named Entity Recognition, NER&#xff09;&#xff1a; 实体识别的目标是从文本中识别出具有特定意义的实体&#xff0…

动手学深度学习(Pytorch版)代码实践 -循环神经网络- 56门控循环单元(`GRU`)

56门控循环单元&#xff08;GRU&#xff09; 我们讨论了如何在循环神经网络中计算梯度&#xff0c; 以及矩阵连续乘积可以导致梯度消失或梯度爆炸的问题。 下面我们简单思考一下这种梯度异常在实践中的意义&#xff1a; 我们可能会遇到这样的情况&#xff1a;早期观测值对预测…

Nacos2.X源码分析:服务注册、服务发现流程

文章目录 Nacos2.1.X源码源码下载服务注册NacosClient端NacosServer端 服务发现NacosClient端NacosServer端 Nacos2.1.X源码 源码下载 源码下载地址 服务注册 官方文档&#xff0c;对于NamingService接口服务注册方法的说明 Nacos2.X 服务注册总流程图 NacosClient端 一个…

华为OSPF配置DR和BDR与指定DR

基础配置 <Huawei>sys #进入配置模式 Enter system view, return user view with CtrlZ. [Huawei]un in en #关闭报文弹窗 Info: Information center is disabled. [Huawei]sys R1 #设备名更改为R1 [R1]int g0/0/0 …