标签: gil

什么是C#的GIL版本?

在CPython的当前实现中,存在称为"GIL"或"Global Interpreter Lock"的对象.它本质上是一个互斥锁,可以防止两个Python线程同时执行Python代码.这可以防止两个线程破坏Python解释器的状态,但也可以防止多个线程真正一起执行.基本上,如果我这样做:

# Thread A
some_list.append(3)
# Thread B
some_list.append(4)
Run Code Online (Sandbox Code Playgroud)

我无法破坏列表,因为在任何给定时间,只有其中一个线程正在执行,因为它们必须持有GIL才能执行此操作.现在,列表中的项目可能会以某种不确定的顺序添加,但关键是列表没有损坏,并且总会添加两件事.

所以,现在到C#.C#基本上面临与Python相同的问题,那么,C#如何阻止这种情况呢?如果有人知道的话,我也有兴趣听Java的故事.


澄清:我对没有显式锁定语句的情况感兴趣,特别是对VM.我知道Java和C#都存在锁定原语 - 它们也存在于Python中:GIL不用于多线程代码,只是为了保持解释器的理智.我对以上的直接等价感兴趣,所以,在C#中,如果我能够记得足够...... :-)

List<String> s;
// Reference to s is shared by two threads, which both execute this:
s.Add("hello");
// State of s?
// State of the VM? (And if sane, how so?)
Run Code Online (Sandbox Code Playgroud)

这是另一个例子:

class A
{
    public String s;
}
// Thread A & B
some_A.s = some_other_value;

// some_A's state must change: how does it change?
// Is the VM still in good …
Run Code Online (Sandbox Code Playgroud)

c# python java gil

8
推荐指数
2
解决办法
996
查看次数

为什么Python提供锁定机制,如果它受GIL的约束?

我知道Python线程一次只能执行一个字节码,那么为什么线程库会提供锁?我假设如果一次只执行一个线程,则不会发生竞争条件.

该库提供锁,条件和信号量.这是同步执行的唯一目的吗?

更新:

我做了一个小实验:

from threading import Thread
from multiprocessing import Process

num = 0

def f():
    global num
    num += 1

def thread(func):
    # return Process(target=func)
    return Thread(target=func)


if __name__ == '__main__':
    t_list = []
    for i in xrange(1, 100000):
        t = thread(f)
        t.start()
        t_list.append(t)

    for t in t_list:
        t.join()

    print num
Run Code Online (Sandbox Code Playgroud)

基本上我应该启动100k线程并递增1.返回的结果是99993.

a)如果有GIL同步和避免竞争条件,结果如何不是99999?b)甚至可以启动100k OS线程吗?

看到答案后更新2:

如果GIL没有真正提供一种方法来执行简单的操作,例如原子递增,那么将它放在那里的目的是什么?它对于讨厌的并发问题没有帮助,那么它为什么要到位呢?我听说过C扩展的用例,有人会举例说明吗?

python multithreading gil locks python-multiprocessing

7
推荐指数
1
解决办法
734
查看次数

Python 中使用多核的线程

据我所知,Python的线程库使用POSIX线程进行线程处理,并且它不能在多核上运行。那么我们是否有可能使用 Open MP 为 Python 线程实现多核线程系统呢?

python pthreads gil python-2.7

7
推荐指数
1
解决办法
1万
查看次数

为什么这个Python脚本在多个内核上的运行速度比单个内核慢4倍

我试图了解CPython的GIL如何工作以及CPython 2.7.x和CPython 3.4.x中GIL之间的区别是什么.我正在使用此代码进行基准测试:

from __future__ import print_function

import argparse
import resource
import sys
import threading
import time


def countdown(n):
    while n > 0:
        n -= 1


def get_time():
    stats = resource.getrusage(resource.RUSAGE_SELF)
    total_cpu_time = stats.ru_utime + stats.ru_stime
    return time.time(), total_cpu_time, stats.ru_utime, stats.ru_stime


def get_time_diff(start_time, end_time):
    return tuple((end-start) for start, end in zip(start_time, end_time))


def main(total_cycles, max_threads, no_headers=False):
    header = ("%4s %8s %8s %8s %8s %8s %8s %8s %8s" %
              ("#t", "seq_r", "seq_c", "seq_u", "seq_s",
               "par_r", "par_c", "par_u", "par_s"))
    row_format = ("%(threads)4d …
Run Code Online (Sandbox Code Playgroud)

python multithreading cpython gil

7
推荐指数
1
解决办法
1286
查看次数

关于python中的GIL

我知道 GIL 会阻止 python 跨内​​核运行其线程。如果是这样,为什么在网络服务器中使用 python,youtube、instagram 等公司如何处理它。

PS:我知道像多处理这样的替代方法可以解决它。但是,如果有人可以将其与他们处理的场景一起发布,那就太好了。

python django web-services gil

7
推荐指数
2
解决办法
1179
查看次数

Flask 中的线程不适用于 UWSGI 但在命令行上工作

我有一个 Flask 应用程序,在命令行上运行时可以正常工作,但是当它通过 uWSGI 运行时,它无法正确响应请求或工作线程无法正常工作。我重写了一个简单的概念验证/失败程序来演示这个问题:

from datetime import datetime
from threading import Event, Thread

from flask import Flask


class JobManager:
    def __init__(self):
        self.running = False
        self.event = Event()

    def start(self):
        self.running = True
        while self.running:
            print("Processing Job at", datetime.now().strftime('%c'))
            self.event.clear()
            self.event.wait(5)
            if self.event.is_set():
                print("Interrupted by request!")

    def stop(self):
        self.running = False
        self.event.set()


app = Flask(__name__)
jobs = JobManager()

t = Thread(target=jobs.start)
t.start()

@app.route('/')
def hello_world():
    global jobs
    jobs.event.set()

    return "I'm alive at " + datetime.now().strftime('%c')


if __name__ == '__main__':
    app.run() …
Run Code Online (Sandbox Code Playgroud)

gil python-multithreading flask uwsgi python-3.x

7
推荐指数
1
解决办法
4346
查看次数

python 3.7多线程中的GIL行为

我正在研究并试图了解 python GIL 和在 python 中使用多线程的最佳实践。我找到了这个演示文稿这个视频

我试图重现演示文稿前 4 张幻灯片中提到的奇怪和疯狂的问题。这个问题老师在视频中也提到过(前4分钟)。我写了这个简单的代码来重现问题

from threading import Thread
from time import time

BIG_NUMBER = 100000
count = BIG_NUMBER


def countdown(n):
    global count
    for i in range(n):
        count -= 1


start = time()
countdown(count)
end = time()
print('Without Threading: Final count = {final_n}, Execution Time = {exec_time}'.format(final_n=count, exec_time=end - start))

count = BIG_NUMBER
a = Thread(target=countdown, args=(BIG_NUMBER//2,))
b = Thread(target=countdown, args=(BIG_NUMBER//2,))
start = time()
a.start()
b.start()
a.join()
b.join()
end = time()
print('With Threading: …
Run Code Online (Sandbox Code Playgroud)

python multithreading gil python-multithreading

7
推荐指数
1
解决办法
1427
查看次数

为什么 ThreadPoolExecutor 的默认 max_workers 是根据 CPU 数量决定的?

的文档concurrent.futures.ThreadPoolExecutor说:

改变在3.5版本中:如果max_workersNone或者没有给出,将默认为机器上的处理器,乘以数量5,假设的ThreadPoolExecutor通常用于重叠I / O,而不是CPU的工作,工人的数量应该更高比ProcessPoolExecutor的工人数量。

我想了解为什么默认max_workers值取决于 CPU 的数量。不管我有多少 CPU,在任何时间点都只能运行一个 Python 线程。

让我们假设每个线程都是 I/O 密集型的,它只有 10% 的时间在 CPU 上,90% 的时间在等待 I/O。然后让我们假设我们有 2 个 CPU。我们只能运行 10 个线程来使用 100% 的 CPU。我们不能再使用 CPU,因为在任何时间点都只有一个线程在运行。即使有 4 个 CPU,也是如此。

那么为什么默认是max_workers根据 CPU 数量来决定的呢?

python cpu performance multithreading gil

7
推荐指数
1
解决办法
3977
查看次数

为什么这个带有线程的 Python 代码有竞争条件?

此代码创建了一个竞争条件:

import threading

ITERS = 100000
x = [0]

def worker():
    for _ in range(ITERS):
        x[0] += 1  # this line creates a race condition
        # because it takes a value, increments and then writes
        # some inrcements can be done together, and lost

def main():
    x[0] = 0  # you may use `global x` instead of this list trick too
    t1 = threading.Thread(target=worker)
    t2 = threading.Thread(target=worker)
    t1.start()
    t2.start()
    t1.join()
    t2.join()

for i in range(5):
    main()
    print(f'iteration {i}. expected x …
Run Code Online (Sandbox Code Playgroud)

python gil python-3.x

7
推荐指数
1
解决办法
1466
查看次数

没有 GIL 的 Python 中的隔离子解释器

PEP-554PEP-684。两者都旨在支持线程级别的多个解释器。

有谁知道这些 PEP 是否至少在 Python 的实验版本或预发布版本(如 3.11)中实现?

我发现 Python 3.10(甚至可能是 3.9)在实验版本中具有这些功能。如果您通过配置以下标志来构建 CPython:

./configure --with-experimental-isolated-subinterpreters

或者在编译所有文件时在编译命令中添加define .c

#define EXPERIMENTAL_ISOLATED_SUBINTERPRETERS 1

我在一个著名的项目中发布了启用此功能的请求,请参阅此处的问题

启用此功能后,我想我将能够在多个线程(而不是进程)内创建单独的解释器,这意味着我不再需要多重处理

更重要的是,根据此功能描述,当使用多个解释器时,不需要有单个 GIL,单独线程中的每个解释器都有自己的 GIL。这意味着即使解释器是在线程内创建的,仍然会使用所有 CPU 核心,就像multiprocessing. 当前的 Python 遭受 GIL 的困扰只是因为它强制只使用单个 CPU 核心,因此multiprocessing人们使用所有 CPU 核心来克服这个问题。

在描述这些功能时,据说作者必须手动修改 1500 个静态和全局变量,将它们全部移动到线程状态结构内的每线程本地表中。

想必所有这些新功能现在只能通过Python C API来使用。

如果这里有人知道如何使用这些独立的子解释器功能,您能否提供一些 Python 代码或 C API 代码以及如何使用它们的详细示例?

具体来说,我感兴趣的是如何以使用所有CPU核心的方式使用解释器,即我想知道如何避免单个GIL,而是使用多个GIL(实际上是本地锁,LIL)。当然,我想要内部线程,而不使用multiprocessing.

python multithreading interpreter python-c-api gil

7
推荐指数
0
解决办法
474
查看次数