Home >Backend Development >Python Tutorial >不同的语言中多进程和多线程具体的原理是什么?

不同的语言中多进程和多线程具体的原理是什么?

WBOY
WBOYOriginal
2016-06-06 16:23:281488browse

python中由于全局锁(GIL)的存在导致多线程并不能利用多核,看了一些资料说,java好像对多线程的处理是可以利用多核的硬件资源的(因为java直接调用的操作系统的多线程接口处理的)。不同的语言对多线程的处理是否能做到利用硬件,主要取决于编译器或者解释器对线程的包装吗?还有python中多进程是怎样一个概念,不是说一个程序只有一个进程,进程里面可以有多个线程,那么python是怎么在一个程序中用多个进程的?

回复内容:

Python中由于全局锁(GIL)的存在导致多线程并不能利用多核,看了一些资料说,Java好像对多线程的处理是可以利用多核的硬件资源的(因为 Java直接调用的操作系统的多线程接口处理的)。不同的语言对多线程的处理是否能做到利用硬件,主要取决于编译器或者解释器对线程的包装吗?

我感觉你括号里那句“因为 Java直接调用的操作系统的多线程接口处理的”好像并不是 Python 和 Java 在多线程上存在差异的原因,你去翻下 Python 源码的 Thread.h 以及相关的一串头文件就会发现,Python 中的线程在 Linux 上是调用了 pthread_create(),在 Windows上是调用了 CreateThread(),都是根正苗红的原生线程

真正导致差异的,其实就是你一开始提到的 GIL,这个跟是不是“直接调用操作系统的多线程接口”没啥关系。其实 Python 的 GIL 只在 CPython 这个实现中存在,Jython 是没有的,Ruby 的 MRI 实现也有 GIL,而 JRuby 就没有 GIL

Python 源码中的 ceval.c 文件有 GIL 刷存在感的现场,比如第 256 行至第 290 行如下所示
<code class="language-c"><span class="kt">void</span>
<span class="nf">PyEval_AcquireLock</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">PyThread_acquire_lock</span><span class="p">(</span><span class="n">interpreter_lock</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>

<span class="kt">void</span>
<span class="nf">PyEval_ReleaseLock</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">PyThread_release_lock</span><span class="p">(</span><span class="n">interpreter_lock</span><span class="p">);</span>
<span class="p">}</span>

<span class="kt">void</span>
<span class="nf">PyEval_AcquireThread</span><span class="p">(</span><span class="n">PyThreadState</span> <span class="o">*</span><span class="n">tstate</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">tstate</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span>
        <span class="n">Py_FatalError</span><span class="p">(</span><span class="s">"PyEval_AcquireThread: NULL new thread state"</span><span class="p">);</span>
    <span class="cm">/* Check someone has called PyEval_InitThreads() to create the lock */</span>
    <span class="n">assert</span><span class="p">(</span><span class="n">interpreter_lock</span><span class="p">);</span>
    <span class="n">PyThread_acquire_lock</span><span class="p">(</span><span class="n">interpreter_lock</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">PyThreadState_Swap</span><span class="p">(</span><span class="n">tstate</span><span class="p">)</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span>
        <span class="n">Py_FatalError</span><span class="p">(</span>
            <span class="s">"PyEval_AcquireThread: non-NULL old thread state"</span><span class="p">);</span>
<span class="p">}</span>

<span class="kt">void</span>
<span class="nf">PyEval_ReleaseThread</span><span class="p">(</span><span class="n">PyThreadState</span> <span class="o">*</span><span class="n">tstate</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">tstate</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span>
        <span class="n">Py_FatalError</span><span class="p">(</span><span class="s">"PyEval_ReleaseThread: NULL thread state"</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">PyThreadState_Swap</span><span class="p">(</span><span class="nb">NULL</span><span class="p">)</span> <span class="o">!=</span> <span class="n">tstate</span><span class="p">)</span>
        <span class="n">Py_FatalError</span><span class="p">(</span><span class="s">"PyEval_ReleaseThread: wrong thread state"</span><span class="p">);</span>
    <span class="n">PyThread_release_lock</span><span class="p">(</span><span class="n">interpreter_lock</span><span class="p">);</span>
<span class="p">}</span>
</code>
GIL这个东西,跟实现有关。java的每一个对象都继承了object类的六个方法,其中包括wait和notify.如果cpython也这么干,就没gil了。实际上,鸟叔曾搞出过这样的python版本,但是由于单线程性能急剧下降,大家不乐意又换成Gil版本了。 多线程难道不是等io用么→_→
以及这玩意主要看实现是怎么实现的
python也有多进程啊(*/ω\*) 第一个问题是的,python无法利用多核是因为其运行时,虚拟机解析器,是单线程的。(估计一开始就设计成这个样子),于是任意个时刻虚拟机能运行上下文只有一份,也只在处理一份python虚拟机指令。多线程其实是假的,通过GIL锁住了运行上下文状态,切换上下文来模拟多线程

进程这个,和语言无关,和操作系统有关。多进程就是利用操作系统功能创建的进程而已,不是在同一个程序中。 有些语言可以调用操作系统API,最直接
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn