8.Lab Sevent —— Multithreading

首先切换到thread分支

git checkout thread
make clean

Uthread:switch between threads

为用户级线程系统设计上下文切换机制

xv6中已经放了两个文件:

  • user/uthread.cuser/uthread_switch.S

  • 以及一个规则:运行在Makefile中以构建uthread程序。

  • uthread.c包含大多数用户级线程包,以及三个简单测试线程的代码。

实现用户级线程切换,比起xv6中实现内核级线程,这个更简单一些,因为用户级线程不需要设计用户栈和内核栈,用户页表和内核页表切换等等

1.定义存储上下文的结构体tcontext(kernel/proc.h)同时修改uthread.c(user/uthread.c)中的thread结构体

2.类似按照kernel/swtch.S,修改user/uthread_switch.S中写入如下代码

3.更改thread_scheduler(user/uthread.c),进行线程的轮询并找到下一个需要执行的切换

其中thread_yield函数是默认提供好的

Using threads

在文件notxv6/ph.c中包含一个简单的哈希表,如果单个线程使用,该哈希表是正确,但是多个线程使用时,该哈希表不正确,可以在主目录中输入如下命令:

make ph
./ph 1

结果如下:

ph的参数指定在哈希表上执行put和get的线程数,可以看到没有missing,100000 puts 也对应 10000 gets

但是当使用多个线程的时候,例如2,结果如下:

$ ./ph 2
100000 puts, 4.385 seconds, 23044 puts/second
1: 16579 keys missing
0: 16579 keys missing
200000 gets, 8.422 seconds, 23597 gets/second

可以看到丢失了不少,但数字确实貌似是二倍的样子,pu运行两个基准程序,通过put()将许多键添加到哈希表,并以秒为单位打印puts的速率,然后它使用get()从哈希表中获取键,打印由于puts而应该在哈希表中单丢失的键的数量。然而,16579 keys missing的两行代表丢失了大量的键

所以这里需要使用多进程必须进行上锁

设定了五个散列桶,根据键除以5的余数来确定插入到哪个散列桶中,插入的方式是头插法

造成数据丢失原因:

  • 假设现在有两个线程T1和T2,两个线程都走到put函数,且假设两个线程中 key%NBUCKET相同

  • 两个线程同时调用insert(key, value, &table[i], table[i]),第一个参数是传需要插入的内存地址,第二个参数是需要插入的某块内存(插入到该内存之前)insert是通过头插法实现的。如果先insert的线程还未返回另一个线程就开始insert,那么前面的数据会被覆盖

1.在notxv6/ph.c为每个散列桶定义一个锁,将五个锁放在一个数组中,并进行初始化

2.在put函数中对insert函数上锁(get不需要,因为不会修改只是读)

加锁后测试:


 

Barrier

实现一个内存屏障(Barrier):

应用程序中的某个点,所有参与的线程都必须在此点上等待,知道其他所有参与的线程也到达该点

在notxv6/barrier.c中包含一个残缺的屏障实现

$ make barrier
$ ./barrier 2
barrier: notxv6/barrier.c:42: thread: Assertion `i == t' failed.

2 指明了在屏障上同步的线程数,每个线程执行一个循环,每次循环迭代中,线程都会调用barrier(),然后以随机微秒数休眠,如果一个线程在另一个线程到达屏障之前离开屏障将触发断言。希望达到的效果是每个线程在barrier()中阻塞,直到nthreads的所有线程都调用了barrier()

看一下notxv6/barrier.c中的代码逻辑(已经完成了barrier函数的实现)

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <assert.h>
#include <pthread.h>static int nthread = 1;
static int round = 0;// 互斥锁,条件变量,到达屏障的线程数、轮数
struct barrier {pthread_mutex_t barrier_mutex;pthread_cond_t barrier_cond;int nthread;      // Number of threads that have reached this round of the barrierint round;     // Barrier round
} bstate;//初始化屏障
static void
barrier_init(void)
{assert(pthread_mutex_init(&bstate.barrier_mutex, NULL) == 0);assert(pthread_cond_init(&bstate.barrier_cond, NULL) == 0);bstate.nthread = 0;
}//屏障函数,已经实现
static void 
barrier()
{// YOUR CODE HERE//// Block until all threads have called barrier() and// then increment bstate.round.////申请锁,互斥操作pthread_mutex_lock(&bstate.barrier_mutex);// judge whether all threads reach the barrierif(++bstate.nthread != nthread)  {    // not all threads reach    pthread_cond_wait(&bstate.barrier_cond,&bstate.barrier_mutex);  // wait other threads} else {  // all threads reachbstate.nthread = 0; // reset nthread++bstate.round; // increase roundpthread_cond_broadcast(&bstate.barrier_cond);   // wake up all sleeping threads}pthread_mutex_unlock(&bstate.barrier_mutex);}//每个线程执行的函数
static void *
thread(void *xa)
{long n = (long) xa;long delay;int i;for (i = 0; i < 20000; i++) {int t = bstate.round;//检查是否实现了所有线程共同达到屏障的效果assert (i == t);//等待所有线程到达屏障barrier();usleep(random() % 100);}return 0;
}int
main(int argc, char *argv[])
{pthread_t *tha;void *value;long i;double t1, t0;if (argc < 2) {fprintf(stderr, "%s: %s nthread\n", argv[0], argv[0]);exit(-1);}//参数指定线程数量nthread = atoi(argv[1]);tha = malloc(sizeof(pthread_t) * nthread);// srandom 是 C 标准库中的一个函数,用于设置伪随机数生成器(PRNG)的起始种子 -- 输出只是伪随机而不是真正的随机数srandom(0);barrier_init();//创建n个线程执行for(i = 0; i < nthread; i++) {assert(pthread_create(&tha[i], NULL, thread, (void *) i) == 0);}for(i = 0; i < nthread; i++) {assert(pthread_join(tha[i], &value) == 0);}printf("OK; passed\n");
}

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Text-to-SQL技术升级 - 阿里云OpenSearch-SQL在BIRD榜单夺冠方法

Text-to-SQL技术升级 - 阿里云OpenSearch-SQL在BIRD榜单夺冠方法 Text-to-SQL 任务旨在将自然语言查询转换为结构化查询语言(SQL),从而使非专业用户能够便捷地访问和操作数据库。近期,阿里云的 OpenSearch 引擎凭借其一致性对齐技术,在当前极具影响力的 Text-to-SQL 任务…

【C++前后缀分解】1888. 使二进制字符串字符交替的最少反转次数|2005

本文涉及知识点 C前后缀分解 LeetCode1888. 使二进制字符串字符交替的最少反转次数 给你一个二进制字符串 s 。你可以按任意顺序执行以下两种操作任意次&#xff1a; 类型 1 &#xff1a;删除 字符串 s 的第一个字符并将它 添加 到字符串结尾。 类型 2 &#xff1a;选择 字符…

点到直线的距离公式证明

根据勾股定理&#xff0c;已知直角三角形的两个直角边长为&#xff0c;&#xff0c;可以计算出斜边长为 进而根据三角形的面积公式&#xff0c;可以求得斜边的高为 下面证点到直线的距离公式&#xff1a; 如上图&#xff0c;知任意点到直线的距离公式为

解决Tez报错问题

在启动hive的时候&#xff0c;发现该报错 1、检测HADOOP_PATH环境变量 echo $HADOOP_CLASSPATH 如果没有输出&#xff0c;说明我们的配置文件没有生效&#xff0c;这时候需要重写source一下 2、刷新配置文件生效 source /etc/profile 有输出&#xff0c;环境生效 3、再次运…

计算机毕业设计 玩具租赁系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

MySQL | 知识 | 从底层看清 InnoDB 数据结构

文章目录 一、InnoDB 简介InnoDB 行格式COMPACT 行格式CHAR(M) 列的存储格式VARCHAR(M) 最多能存储的数据记录中的数据太多产生的溢出行溢出的临界点 二、表空间文件的结构三、InnoDB 数据页结构页页的概览Infimum 和 Supremum使用Page Directory页的真实面貌 四、B 树是如何进…

基于SpringBoot+Vue的房屋租赁平台

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于JavaSpringBootVueMySQL的…

如何使用ssm实现企业人事管理系统+vue

TOC ssm628企业人事管理系统vue 研究背景 自计算机发展以来给人们的生活带来了改变。第一代计算机为1946年美国设计&#xff0c;最开始用于复杂的科学计算&#xff0c;占地面积、开机时间要求都非常高&#xff0c;经过数十几的改变计算机技术才发展到今天。现如今已是电子时…

echarts map地图动态下钻,自定义标注,自定义tooltip弹窗【完整demo版本】

在数据可视化中&#xff0c;地图是很重要的一个环节&#xff0c;很多时候需要展现的不仅是国家地图&#xff0c;还需要能从国家进入到省市。这个逐级进入的过程就是我们今天说的地图下钻。 地图下钻看起来很屌、很高大上&#xff0c;但是仔细琢磨一下&#xff0c;技术实现上真的…

爵士编曲:爵士鼓编写 爵士鼓笔记 底鼓和军鼓 闭镲和开镲 嗵鼓

底鼓和军鼓 底鼓通常是动的音色&#xff0c;军鼓通常是大的音色。 “动”和“大”构成基础节奏。“动大”听着不够有连接性&#xff0c;所以可以加入镲片&#xff01; 开镲 直接鼓棒敲击是开镲音色 闭镲 当脚踩下踏板&#xff0c;2个镲片合并&#xff0c;然后用鼓棒敲击&am…

R语言NHANES数据分析(2)

#交互分析 library(jstable) help(package"nhanesA") help(package"jstable") str(data_c) svy_design$variables$DMDCITZN<-as.factor(svy_design$variables$DMDCITZN) TableSubgroupMultiGLM(BPQ020~BMXBMI,datasvy_design,var_subgroups c("DM…

【AIGC】Kolors:快手开源的文生图大模型

GitHub&#xff1a;GitHub - Kwai-Kolors/Kolors: Kolors Team 论文&#xff1a;Kolors/imgs/Kolors_paper.pdf at master Kwai-Kolors/Kolors GitHub comfyui&#xff1a;GitHub - comfyanonymous/ComfyUI: The most powerful and modular diffusion model GUI, api and b…

【UEFI基础】BIOS下的启动项管理

启动管理 启动管理&#xff08;Boot Manager&#xff09;是UEFI BIOS中重要的一部分&#xff0c;它通过一系列的变量来确定启动策略&#xff0c;包括&#xff1a; 执行启动还是恢复操作启动顺序是如何 本文会介绍下面的内容&#xff1a; 与启动管理相关的变量启动或恢复的流…

关于STM32项目面试题02:ADC与DAC篇(输入部分NTC、AV:0-5V、AI:4-20mA和DAC的两个引脚)

博客的风格是&#xff1a;答案一定不能在问题的后面&#xff0c;要自己想、自己背&#xff1b;回答都是最精简、最精简、最精简&#xff0c;可能就几个字&#xff0c;你要自己自信的展开。 面试官01&#xff1a;什么是模数转换/ADC&#xff1f;说说模数转换的流程&#xff1f; …

『功能项目』靠近Npc显示可对话标识【60】

我们打开上一篇59窗口可拖拽脚本的项目&#xff0c; 本章要做的事情是在资源加载时加载Npc01并且实现主角靠近Npc01时&#xff0c;显示可对话标识&#xff0c;当按键盘G键时弹出对话内容 首先在资源场景中加载一个Npc模型 导入&#xff08;除脚本&#xff09;外的资源 在资源文…

PAT甲级-1055 The World‘s Richest

题目 题目大意 输入给出富人的总数以及富人的姓名、年龄、财富&#xff0c;接下来的k行给出需要排序的个数&#xff0c;每个排序要求输出m个富人&#xff0c;并且限制了年龄段&#xff0c;[Amin, Amax]。要求输出所有的排序。如果满足年龄段的人数为0&#xff0c;就输出None。…

Windows目录监控部署

1.前提 Cell_Directory_Monitoring.bat脚本用到的du命令,请协调Windows系统管理员提供。 下述du命令部署配置方式仅供参考,如要部署,请协调Windows系统管理员协助确认其不会对系统造成异常。 1.1.du.exe部署 1.将x32位du.exe文件放入如下目录 目录:C:\Windows\System3…

如何在win10Docker安装Mysql数据库?

1.拉取镜像 docker pull mysql 2.查看镜像 使用以下命令来查看是否已安装了 mysql镜像。 3.运行镜像 命令&#xff1a; docker run -p 3306:3306 --name mysql --restartalways --privilegedtrue \ -v /usr/local/mysql/log:/var/log/mysql \ -v /usr/local/mysql/data:/var…

机器学习-点击率预估-论文速读-20240916

1. [经典文章] 特征交叉: Factorization Machines, ICDM, 2010 分解机&#xff08;Factorization Machines&#xff09; 摘要 本文介绍了一种新的模型类——分解机&#xff08;FM&#xff09;&#xff0c;它结合了支持向量机&#xff08;SVM&#xff09;和分解模型的优点。与…