from threading import Thread def countdown(start, end): while end > start: end -= 1 def single_thread(n): countdown(0, n) def multi_thread(n): t1 = Thread(target=countdown, args=(0, n // 2)) t2 = Thread(target=countdown, args=(n // 2, n)) t1.start() t2.start() t1.join() t2.join() if __name__ == '__main__': import timeit import sys sys.setswitchinterval(1) print(timeit.timeit("""import gil;gil.multi_thread(10000000);""", number=1)) # 1.07s sys.setswitchinterval(0.001) print(timeit.timeit("""import gil;gil.multi_thread(10000000);""", number=1)) # 1.09s
按照我的理解,将切换间隔设置的更小,导致更多次的线程睡眠 /唤醒操作,然后总的执行时间应该变长,但是这里并没有,谁能告诉我是为什么吗? 测试环境为:四核 Ubuntu python3.5
![]() | 1 enenaaa 2018-05-20 17:26:25 +08:00 第一, 线程切换时间依赖于操作系统。 第二, 这个值只是解释器估计的理想时间。在执行较长的函数内并不会主动中断。因为解释器没有线程调度功能, 需要依赖系统。 |
![]() | 2 chenxytw 2018-05-21 14:15:52 +08:00 |
3 jfry OP @enenaaa @chenxytw 我是看了一个讲 Python3 GIL 的 PDF 之后做的这个实验,根据这个 PDF 中的描述,当两个线程 A,B 同时运行的时候,假如 A 正在运行,此时 B 会阻塞直到超时,然后设置 gil_drop_request 为 1,A 检测到之后就会释放 GIL 并且通过信号唤醒 B,因此我理解的是此时操作系统就会让 A 睡眠,然后调度 B .是我理解错了吗? PDF 地址: http://www.dabeaz.com/python/NewGIL.pdf |
![]() | 4 enenaaa 2018-05-22 09:53:24 +08:00 via Android @jfry 线程切换的条件一是当前线程主动挂起,二是当前时间片用完。这两个条件都由系统决定,解释器是在系统切换完之后加锁。setswitchinterval 只是在解释器加锁时的一个参照时间,而不是系统的时间片时间。 这个程序里线程一直在运行,用满系统时间片。导致解释器无从按指定参数去控制。 |