用解释程序交错执行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"); elseif(pi==&result.b) printf("b"); elseif(pi==&result.c) printf("c"); elseif(pi==&result.t1) printf("t1"); elseif(pi==&result.t2) printf("t2");if(pi==a->left) {printf("=");pi=a->right;}}if(nl)printf(";\n");elseprintf(";");
}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.mzph.cn/pingmian/42511.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Paho Asynchronous MQTT C Client Library--MQTTAsync API

异步MQTT 客户端库for C 基于C语言编写的MQTTAsync API&#xff0c;版权属于IBM&#xff0c;适用于2009年至2018年。 Paho MQTT C库中的API分为两类&#xff1a; 同步API&#xff08;MQTTClient API&#xff09; 特点&#xff1a;被认为是更易于使用&#xff0c;部分函数调用…

TypeScript 中的 interface

在 TypeScript 中&#xff0c;interface 是一种定义对象结构或“形状”&#xff08;shape&#xff09;的类型。它可以指定一个对象必须具有的属性、方法以及它们的数据类型。通过使用 interface&#xff0c;你可以确保对象实例遵循特定的模式或契约。 以下是 interface 的一些…

昇思25天学习打卡营第12天|sea_fish

打开第12天&#xff0c;前几天打卡完成了入门的学习&#xff0c;后续有时间对入门的内容&#xff0c;再次整理一下。本次学习的内容为基于MindSpore的GPT2文本摘要。记录学习的过程。记录实验系统中的步骤&#xff0c;对一些内容进行记录和归纳。 数据集加载与处理 数据集加载…

归并排序详解(递归与非递归)

归并排序是建立在归并操作上的一种有效算法。该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并&#xff0c;得到完全有序的序列&#xff1b;即先使每个子序列有序&#xff0c;再使子序列间断有序。若将两个有序表合并成一个有序表&#xff0c;成为二路归并。 一…

【6】图像分类部署

【6】图像分类部署 文章目录 前言一、将pytorch模型转为ONNX二、本地终端部署2.1. ONNX Runtime部署2.2. pytorch模型部署&#xff08;补充&#xff09; 三、使用flask的web网页部署四、微信小程序部署五、使用pyqt界面化部署总结 前言 包括将训练好的模型部署在本地终端、web…

【Android】自定义换肤框架01之皮肤包制作

前言 目前为止&#xff0c;市面上主流的安卓换肤方案&#xff0c;其实原理都是差不多的 虽然大多都号称一行代码集成&#xff0c;但其实想要做到完全适配&#xff0c;并不简单 这个系列&#xff0c;就是让大家从零开始&#xff0c;完全掌握这方面知识&#xff0c;这样才能对…

关于vue监听数组

Vue.js 监听数组&#xff1a;深入理解与实践 在 Vue.js 开发中&#xff0c;数据的响应式更新是其核心特性之一。当我们处理数组时&#xff0c;如何高效地监听数组的变化&#xff0c;及时更新视图&#xff0c;是每个开发者都需要掌握的技能。本文将深入探讨 Vue.js 监听数组的机…

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怎…

Automatic TSPITR in 10G RMAN 19C DBV expdp “TEST” RAC中 thread

TSPITR 注意事项&#xff1a; 19C DBV expdp 不用exp imp “TEST” 一定要“” 起来&#xff0c;否则说找不到test tablespace. RAC中 thread 要指定对&#xff0c;否则过度恢复。 SEQUENCE# 是drop 时的&#xff0c;不是创建时的。 tablespace 默认是offline的&#xf…

【WPF】桌面程序开发之xaml页面基础布局方式详解

使用Visual Studio开发工具&#xff0c;我们可以编写在Windows系统上运行的桌面应用程序。其中&#xff0c;WPF&#xff08;Windows Presentation Foundation&#xff09;项目是一种常见的选择。然而&#xff0c;对于初学者来说&#xff0c;WPF项目中xaml页面的布局设计可能是一…

EtherCAT转Profinet网关配置说明第三讲:博图配置

EtherCAT协议转Profinet协议网关模块&#xff08;XD-ECPNS20&#xff09;是实现EtherCAT协议和Profinet协议之间无缝通讯的重要设备。使EtherCAT协议和Profinet协议能够相互转换&#xff0c;进行工控自动化里的互连和传送数据。 EtherCAT作为一种高性能实时以太网通信协议&…

11、广告-数据统计原理

数据统计原理 数据统计是程序化广告中非常重要的一环&#xff0c;通过对广告数据和用户行为数据的统计分析&#xff0c;广告主可以评估广告效果、优化投放策略&#xff0c;提升用户转化率和广告收益。以下是关于数据统计原理的详细介绍&#xff1a; 一、Web统计逻辑 浏览器请…

【讲解下iOS语言基础】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

1431. 拥有最多糖果的孩子

1431. 拥有最多糖果的孩子 题目链接&#xff1a;1431. 拥有最多糖果的孩子 代码如下&#xff1a; class Solution { public:vector<bool> kidsWithCandies(vector<int>& candies, int extraCandies) {vector<bool> res(candies.size(),false);int max…

2024中国深圳国际新能源暨清洁能源产业展览会(高交会)

105个国家、5000家参展商、40万㎡展览规模、50万买家客户参观&#xff0c;高交会清洁能源展11月中旬将盛大启幕&#xff1b; ——在科技日新月异、产业融合加速的时代浪潮中&#xff0c;一场备受瞩目的科技盛会即将拉开帷幕&#xff0c;「第二十六届中国国际储能技术与设备展览…

【Linux详解】进程等待 | 非阻塞轮询

引入&#xff1a; 为什么&#xff1f;是什么&#xff1f;怎么办 是什么&#xff1f; 进程等待是指父进程暂停自己的执行&#xff0c;直到某个特定的子进程结束或发生某些特定的事件。 为什么&#xff1f; 僵尸进程刀枪不入&#xff0c;不可被杀死&#xff0c;存在内存泄露…

Linux_实现简易日志系统

目录 1、认识可变参数 2、解析可变参数 3、打印可变参数 3.1 va_list 3.2 va_start 3.3 va_arg 3.4 va_end 3.5 小结 4、实现日志 4.1 日志左半部分 4.2 日志右半部分 4.3 日志的存档归类 结语 前言&#xff1a; 在Linux下实现一个日志系统&#xff0c;该日…

ffmpeg图片视频编辑器工具的安装与使用

title: ffmpeg图片视频编辑器工具的安装与使用 tags: [ffmpeg, 图片, 音频, 视频, 工具, 流媒体] categories: [工具, ffmpeg] FFmpeg是一个开源的命令行工具&#xff0c;广泛用于处理视频和音频文件&#xff0c;包括转换格式、剪辑、混流、解码、编码等。以下是一些基本的FFmp…

Gunicorn配置指南:掌握最大并发连接数设置

摘要 Gunicorn 是一个 Python WSGI HTTP 服务器&#xff0c;广泛用于生产环境中部署 Python web 应用。合理配置 Gunicorn 的最大并发连接数对于优化服务器性能和资源利用至关重要。本文将详细介绍如何在 Gunicorn 中配置最大并发连接数&#xff0c;并探讨相关的配置选项和最佳…

补充:特征缩放技术(归一化与标准化)与学习率的选取和特征转换符合高斯分布

文章目录 前言一、特征缩放技术1. 标准化(Standardization)2. 归一化(Normalization)3 sklearn高级接口二、学习率的选取三、将特征转换为近似符合高斯分布1. 取对数变换(Log Transformation)原理为什么有效?2. 平方根变换(Square Root Transformation)原理为什么有效…