永泰建设工程网站,上海高端网站建设服务公,软件开发工程师需要考什么证书,预付做网站定金如何线程这个概念早在多核CPU出现之前就提出来了#xff0c;单核时代的多线程主要是为了让CPU尽量不处于空闲状态#xff0c;使其计算能力始终能得到利用。但本质上讲#xff0c;在任意时刻只有一个线程在执行。 尽管任意时刻只有一个线程在执行#xff0c;但是依然有些问题需要…线程这个概念早在多核CPU出现之前就提出来了单核时代的多线程主要是为了让CPU尽量不处于空闲状态使其计算能力始终能得到利用。但本质上讲在任意时刻只有一个线程在执行。 尽管任意时刻只有一个线程在执行但是依然有些问题需要解决其中最重要的就是线程安全。这个问题的来源很简单我之前说过CPU对指令是一条一条执行的不过要注意的是高级语言中的一行代码在汇编语言层面上可能由多条汇编指令组成的。举一个简单的例子在c语言中对某个变量做自增操作 int a 0;
int add(){a 1;return a;
} 不过变成汇编指令就不这么简单了,其中实现自增的主要是这两条指令大部分指令省略 movl a(%rip), %eaxaddl $1, %eax 这里之所以在例子中使用全局变量是因为线程安全和数据同步主要是针对全局变量这类可以共享的资源。上面的a(%rip)表示全局变量a的值%eax是一个寄存器。第一条指令表示把a的值保存在eax寄存器中第二条指令对eax中的值加上1。 我们来考虑一个情况现在有两个线程AB都要调用add()函数那么a的预期值应该是2。如果线程A执行完第一条指令后发生了上下文切换此时eax寄存器的值是a的初始值0CPU去执行线程B线程B执行完毕后把1返回给a(%rip)再恢复执行线程A由于线程A不会再去执行第一条指令因此eax寄存器的值不会被更新依旧是0线程A执行完毕后把1返回给a(%rip)。最终a(%rip)的值是1而不是2。 上面这种情况就是我们常说的数据不同步或者线程不安全。对此人们提出了很多方法比如原子操作互斥锁等等出发点主要是以下两种 保证操作不被线程调度机制打断要么全部完成要么全部不做即使操作被线程调度机制打断别的线程也无法获得相关资源的使用权。现在回到python这门语言上。荷兰人Guido van Rossum为了打发时间于1989年发明了脚本语言python。和java类似python源码首先会被编译成字节码python项目中的pyc文件然后由解释器进行解释。类似于在高级语言和汇编语言之间还多了一层中间语言。 上图中一个python表达式可以由多个解释器指令构成一个解释器指令又可以被分成多个汇编指令这意味着一个解释器指令可能在执行过程中被打断事实也确实是这样python的解释器CPython并不是线程安全的。所以为了保证线程安全首先要做到让一个解释器指令能不受线程调度影响被执行完毕对此python解释器的开发者们捣鼓出了python全局解释器锁简称GIL。GIL在任一时刻只允许运行一个线程当一个线程执行时间达到阈值时释放GIL这样连线程调度也变得简单了许多。 那么GIL是不是解决了线程安全的问题了呢没有。这是python中的一个深坑。下一篇博客我会写一些自己在学习GIL时的心得。 转载于:https://www.cnblogs.com/bugsheep/p/9008396.html