我的编程空间,编程开发者的网络收藏夹
学习永远不晚

线程调度的随机性有哪些

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

线程调度的随机性有哪些

这篇文章主要讲解了“线程调度的随机性有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“线程调度的随机性有哪些”吧!

 

线程调度的几个基本知识点

多线程并发执行时有很多同学捋不清楚调度的随机性会导致哪些问题,要知道如果访问临界资源不加锁会导致一些突发情况发生甚至死锁。

关于线程调度,需要深刻了解以下几个基础知识点:

调度的最小单位是轻量级进程【比如我们编写的hello world最简单的C程序,执行时就是一个轻量级进程】或者线程;

每个线程都会分配一个时间片,时间片到了就会执行下一个线程;

线程的调度有一定的随机性,无法确定什么时候会调度;

在同一个进程内,创建的所有线程除了线程内部创建的局部资源,进程创建的其他资源所有线程共享;比如:主线程和子线程都可以访问全局变量,打开的文件描述符等。

实例

再多的理论不如一个形象的例子来的直接。

预期代码时序

假定我们要实现一个多线程的实例,预期程序执行时序如下:

线程调度的随机性有哪些

期待时序

期待的功能时序:

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. 主进程创建子线程,子线程函数function();

  3. 主线程count自加,并分别赋值给value1,value2;

  4. 时间片到了后切换到子线程,子线程判断value1、value2值是否相同,如果不同就打印信息value1,value2,count的值,但是因为主线程将count先后赋值给了value1,value2,所以value1,value2的值应该永远不相同,所以不应该打印任何内容;

  5. 重复2、3步骤。

代码1

好了,现在我们按照这个时序编写代码如下:

1 #include <stdio.h>   2 #include <stdlib.h>   3 #include <string.h>   4 #include <pthread.h>   5 #include <unistd.h>   6    7 unsigned int value1,value2, count=0;   8 void *function(void *arg);   9 int main(int argc,  char *argv[])  10 {  11     pthread_t  a_thread;  12   13     if (pthread_create(&a_thread, NULL, function, NULL) < 0)  14     {  15         perror("fail to pthread_create");  16         exit(-1);  17     }  18     while ( 1 )  19     {  20         count++;  21         value1 = count;  22         value2 = count;  23     }  24     return 0;  25 }  26   27 void  *function(void *arg)  28 {  29     while ( 1 )  30     {  31         if (value1 != value2)  32         {                                                                                                                                                                                           33             printf("count=%d , value1=%d, value2=%d\n",  count, value1, value2);  34             usleep(100000);  35         }       36     }  37     return  NULL;  38 }

乍一看,该程序应该可以满足我们的需要,并且程序运行的时候不应该打印任何内容,但是实际运行结果出乎我们意料。

编译运行:

gcc test.c -o run -lpthread ./run

代码1执行结果

执行结果:

线程调度的随机性有哪些

可以看到子程序会随机打印一些信息,为什么还有这个执行结果呢?其实原因很简单,就是我们文章开头所说的,线程调度具有䘺随机性,我们无法规定让内核何时调度某个线程。有打印信息,那么这说明此时value1和value2的值是不同的,那也说明了调度子线程的时候,是在主线程向value1和value2之间的位置调度的。

代码1执行的实际时序

实际上代码的执行时序如下所示:

线程调度的随机性有哪些

如上图,在某一时刻,当程序走到**value2 =  count;**这个位置的时候,内核对线程进行了调度,于是子进程在判断value1和value2的值的时候,发现这两个变量值不相同,就有了打印信息。

该程序在下面这两行代码之间调度的几率还是很大的。

value1 = count;  value2 = count;

解决方法

如何来解决并发导致的程序没有按预期执行的问题呢?对于线程来说,常用的方法有posix信号量、互斥锁,条件变量等,下面我们以互斥锁为例,讲解如何避免代码1的问题的出现。

互斥锁的定义和初始化:

pthread_mutex_t  mutex; pthread_mutex_init(&mutex, NULL)

申请释放锁:

pthread_mutex_lock(&mutex); pthread_mutex_unlock(&mutex);

原理:进入临界区之前先申请锁,如果能获得锁就继续往下执行, 如果申请不到,就休眠,直到其他线程释放该锁为止。

代码2

1 #include <stdio.h>  2 #include <stdlib.h>  3 #include <string.h>  4 #include <pthread.h>  5 #include <unistd.h>  6 #define _LOCK_  7 unsigned int value1,value2, count=0;  8 pthread_mutex_t  mutex;  9 void *function(void *arg); 10  11 int main(int argc,  char *argv[]) 12 { 13     pthread_t  a_thread; 14           15     if (pthread_mutex_init(&mutex, NULL) < 0)                                                                                                                                                           16     { 17         perror("fail to mutex_init"); 18         exit(-1); 19     } 20  21     if (pthread_create(&a_thread, NULL, function, NULL) < 0) 22     { 23         perror("fail to pthread_create"); 24         exit(-1); 25     } 26     while ( 1 ) 27     { 28         count++; 29 #ifdef  _LOCK_ 30         pthread_mutex_lock(&mutex); 31 #endif 32         value1 = count; 33         value2 = count; 34 #ifdef  _LOCK_ 35         pthread_mutex_unlock(&mutex); 36 #endif 37     } 38     return 0; 39  } 0  41 void  *function(void *arg) 42 { 43      while ( 1 ) 44      { 45 #ifdef _LOCK_ 46         pthread_mutex_lock(&mutex); 47 #endif            48  49         if (value1 != value2)   50         { 51             printf("count=%d , value1=%d, value2=%d\n",  count, value1, value2); 52             usleep(100000); 53         }      54 #ifdef _LOCK_ 55         pthread_mutex_unlock(&mutex); 56 #endif 57      } 58      return  NULL; 59  }

如上述代码所示:主线程和子线程要访问临界资源value1,value2时,都必须先申请锁,获得锁之后才可以访问临界资源,访问完毕再释放互斥锁。该代码执行之后就不会打印任何信息。我们来看下,如果程序在下述代码之间产生调度时,程序的时序图。

value1 = count;  value2 = count;

时序图如下:

线程调度的随机性有哪些


如上图所示:

  1. 时刻n,主线程获得mutex,从而进入临界区;

  2. 时刻n+1,时间片到了,切换到子线程;

  3. n+2时刻子线程申请不到锁mutex,所以放弃cpu,进入休眠;

  4. n+3时刻,主线程释放mutex,离开临界区,并唤醒阻塞在mutex的子线程,子线程申请到mutex,进入临界区;

  5. n+4时刻,子线程离开临界区,释放mutex。

可以看到,加锁之后,即使主线程在value2 =count;  之前产生了调度,子线程由于获取不到mutex,会进入休眠,只有主线程出了临界区,子线程才能获得mutex,访问value1和value2,就永远不会打印信息,就实现了我们预期的代码时序。

感谢各位的阅读,以上就是“线程调度的随机性有哪些”的内容了,经过本文的学习后,相信大家对线程调度的随机性有哪些这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

线程调度的随机性有哪些

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

linux线程调度的方法有哪些

Linux 线程调度的方法有以下几种:1. 时间片轮转调度(Time Slicing):每个线程被分配一个时间片,在时间片用完之后,调度器会切换到下一个线程。这种调度方法适用于多个线程共享 CPU 的情况。2. 优先级调度(Priority
2023-10-21

Java中有哪些线程调度的方式

Java中有哪些线程调度的方式?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。Java的特点有哪些Java的特点有哪些1.Java语言作为静态面向对象编程语言的代
2023-06-14

Java中的随机数有哪些

本篇内容介绍了“Java中的随机数有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!众所周知,随机数是任何一种编程语言最基本的特征之一。而
2023-06-17

python中有哪些线程调用的方式

这期内容当中小编将会给大家带来有关python中有哪些线程调用的方式,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。1 直接调用import threadingimport time def sayhi(n
2023-06-04

JAVA随机数的方法有哪些

本篇内容介绍了“JAVA随机数的方法有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!方法1://利用固定数组长度n,通过n的变化来实现。
2023-06-17

【JavaSE专栏84】线程让步,一种线程调度的机制

作者主页:Designer 小郑 作者简介:3年JAVA全栈开发经验,专注JAVA技术、系统定制、远程指导,致力于企业数字化转型,CSDN学院、蓝桥云课认证讲师。 主打方向:Vue、SpringBoot、微信小程序 本文讲解了 Jav
2023-08-30

php实现随机的函数有哪些

php实现随机的函数有:1、rand(),可生成随机整数;2、mt_rand();3、array_rand(),可返回数组中的一个随机键名;4、shuffle(),可随机打乱数组;5、str_shuffle();6、uniqid()。
2015-11-03

Oracle随机函数的特点有哪些

Oracle随机函数的特点有以下几点:生成均匀分布的随机数:Oracle随机函数能够生成均匀分布的随机数,确保每个可能的值出现的概率相等。可以生成不同类型的随机数:Oracle随机函数可以生成不同数据类型的随机数,包括整数、小数、日期等。可
Oracle随机函数的特点有哪些
2024-04-09

Hadoop Yarn的资源调度器有哪些

这篇文章主要介绍“Hadoop Yarn的资源调度器有哪些”,在日常操作中,相信很多人在Hadoop Yarn的资源调度器有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Hadoop Yarn的资源调度器
2023-06-02

kubernetes调度优化的方法有哪些

Kubernetes调度优化的方法有以下几种:资源限制和需求管理:Kubernetes可以通过资源限制和需求管理来优化调度。资源限制可以确保容器只分配到它们所需的资源量,避免资源浪费;需求管理可以确保容器只在有足够资源的节点上调度,避免节点
2023-10-27

java生成随机数的方法有哪些

Java生成随机数的方法有以下几种:1. 使用`java.util.Random`类:可以使用`nextInt()`方法生成一个随机整数,也可以使用`nextDouble()`方法生成一个随机浮点数。2. 使用`Math.random()`
2023-08-31

C++产生随机数的方法有哪些

这篇文章主要介绍“C++产生随机数的方法有哪些”,在日常操作中,相信很多人在C++产生随机数的方法有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++产生随机数的方法有哪些”的疑惑有所帮助!接下来,请跟
2023-07-05

JS生成随机数的方法有哪些

JS生成随机数的方法有以下几种:1. Math.random():返回一个0到1之间的随机浮点数。```javascriptvar randomNum = Math.random();```2. Math.floor(Math.random
2023-09-12

Java中的多线程调试基础知识有哪些

今天就跟大家聊聊有关Java中的多线程调试基础知识有哪些,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。多线程调试基础  最有价值的调试工具是以线程为中心的。大部分 Java 错误都与
2023-06-03

Java中多线程的中断机制有哪些

本篇文章为大家展示了Java中多线程的中断机制有哪些,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。1、interrupt()public void interrupt() { if (this !
2023-05-30

Spark任务调度器的作用有哪些

任务调度:Spark任务调度器负责安排和调度Spark作业中的任务执行顺序和分配资源,确保任务以最优的方式完成。资源分配管理:Spark任务调度器负责管理和分配集群中的资源,包括内存、CPU等资源,以确保任务能够按时完成。故障恢复:Sp
Spark任务调度器的作用有哪些
2024-03-04

Java的线程池有哪些

这篇文章主要讲解了“Java的线程池有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java的线程池有哪些”吧!线程池简介 线程池的概念:线程池就是首先创建一些线程,它们的集合称为线程池
2023-06-02

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录