千家信息网

线程调度的随机性有哪些

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,这篇文章主要讲解了"线程调度的随机性有哪些",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"线程调度的随机性有哪些"吧!线程调度的几个基本知识点多线程并发
千家信息网最后更新 2026年11月02日线程调度的随机性有哪些

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

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

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

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

调度的最小单位是轻量级进程【比如我们编写的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    2 #include    3 #include    4 #include    5 #include    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   2 #include   3 #include   4 #include   5 #include   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,就永远不会打印信息,就实现了我们预期的代码时序。

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

线程 调度 代码 时序 程序 随机性 信息 时刻 进程 时候 资源 内容 时间 结果 问题 相同 之间 实际 就是 知识 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 北京路客互联网科技有限公司 厦门中拓互联网络科技有限公司 河南真二互联网科技有限公司 互联网巨头科技公司 互联网科技未来 互联网科技媒体 长亮科技互联网金融 互联网科技公司的市场部门 开启互联网科技时代小说 荆州市昕露互联网络科技有限公司 成都互联网科技公司工作好不好 国大互联网教育科技有限公司工作 中国互联网公司排名锤子科技 互联网科技的全部知识 互联网在线教育科技创业 明优互联网科技有限公司 云南省自由互联网科技有限公司 中国互联网公司的科技投入 玉溪新华互联网科技怎么选 互联网科技的前景 科技与互联网发展 卓越科技(互联网 ) 甘肃拓世互联网科技有限公司 苏州铭阳互联网科技有限公司 华中科技大学互联网的牛人 深圳互联网科技的发展 梅州GM互联网络科技有限公司 四川互联网展示科技馆设计 西安左小互联网科技有限公司 保山浩联互联网科技有限公司
0