<p>吉尔保护着Python的内部。这意味着:</p>
<ol>
<li>您不必担心由于多线程而导致解释器出错</li>
<li>大多数事情并不是真正并行运行的,因为python代码是按顺序执行的,这是由于GIL</li>
</ol>
<p>但是GIL不保护你自己的代码。例如,如果您有以下代码:</p>
<pre><code>self.some_number += 1
</code></pre>
<p>它将读取<code>self.some_number</code>的值,计算<code>some_number+1</code>,然后将其写回<code>self.some_number</code>。在</p>
<p>如果在两个线程中执行此操作,则一个线程和另一个线程的操作(读、加、写)可能会混合在一起,因此结果是错误的。在</p>
<p>这可能是执行顺序:</p>
<ol>
<li>thread1读取<code>self.some_number</code>(0)</li>
<li>线程2读取<code>self.some_number</code>(0)</li>
<li>thread1计算<code>some_number+1</code>(1)</li>
<li>thread2计算<code>some_number+1</code>(1)</li>
<li>thread1将1写入<code>self.some_number</code></li>
<li>thread2将1写入<code>self.some_number</code></li>
</ol>
<p>您可以使用锁强制执行以下执行顺序:</p>
<ol>
<li>thread1读取<code>self.some_number</code>(0)</li>
<li>thread1计算<code>some_number+1</code>(1)</li>
<li>thread1将1写入<code>self.some_number</code></li>
<li>线程2读取<code>self.some_number</code>(1)</li>
<li>thread2计算<code>some_number+1</code>(2)</li>
<li>thread2将2写入<code>self.some_number</code></li>
</ol>
<h2>编辑:让我们用一些代码来完成这个答案,这些代码显示了所解释的行为:</h2>
^{pr2}$
<p>有两个函数实现增量。一个用锁,另一个不用。在</p>
<p>函数<code>increment_in_x_threads</code>在许多线程中实现递增函数的并行执行。在</p>
<p>现在,使用足够多的线程运行它,几乎可以肯定会发生错误:</p>
<pre><code>print('unsafe:')
increment_in_x_threads(70, increment_n_times, 100000)
print('\nwith locks:')
increment_in_x_threads(70, safe_increment_n_times, 100000)
</code></pre>
<p>在我的例子中,它打印了:</p>
<pre><code>unsafe:
finished in 0.9840562343597412s.
total: 4654584
expected: 7000000
difference: 2345416 (33.505942857142855 %)
with locks:
finished in 20.564176082611084s.
total: 7000000
expected: 7000000
difference: 0 (0.0 %)
</code></pre>
<p>因此,如果没有锁,就会出现很多错误(33%的增量失败)。另一方面,加上锁,速度慢了20倍。在</p>
<p>当然,这两个数字都被放大了,因为我使用了70个线程,但这显示了总体思路。在</p>