o7412369815963
Не в этом дело, из-за GIL в один момент времени работает только один питон код, остальные ждут. (вне зависимости потоко безопасен или нет)
просто задайся вопросом, почему GIL вообще существует ?
o7412369815963
py.user.next
не, я запущу обычную работу со списком
Зачем?
ну, чтобы провести вычисления
никогда вычисления с использованием списка не проводил ?
o7412369815963
1) Одновременный запуск f1+f1 - работает в 2 раза медленней чем f1
дожидаться нужно завершения каждого потока
плюс, там ещё основной поток (три потока там)
свой результат:
[guest@localhost threadcmp]$ ./thread_сmp2.py
[0.3121845519999624, 0.3115454389990191, 0.30946677799875033]
[0.7022323320015857, 0.6940970079995168, 0.6638078140003927]
[guest@localhost threadcmp]$
o7412369815963
т.е. два “потокобезопасные” lst все равно тормозят - не работают в один момент.
а с чего они будут работать, если они не потокобезопасные ?
то, что в них не ведётся одновременная запись, не делает их потокобезопасными
GIL их и блокирует по очереди, чтобы в них сразу два потока не писали (вообще любые два потока)
o7412369815963
2) f1 запущенный в отдельном потоке работе почти с той же скоростью - с “потокобезопасным” lst
это вообще зачем приведено ?
почти с той же скоростью, потому что время уходит на переключения между главным потоком и дочерним и на вызов констуктора класса Thread() и методов .start() и .join()
o7412369815963
3) а тут вообще работа с lst идет из 3-х потоков, при этом скорость почти не падает.
это где там третий ?
o7412369815963
т.е. пункты 1 и 3 показывают что “не является потокобезопасным” ни причем.
вот работа из трёх потоков: главного, первого дочернего и второго дочернего
(добавил одну строку к третьему коду)
#!/usr/bin/env python3
import timeit
import threading
lst = []
def lf():
del lst[:]
for i in range(10000):
lst.append(i)
def f1():
lf()
lf()
def f2():
lf()
t = threading.Thread(target=lf)
t.start()
#t.join()
t = threading.Thread(target=lf)
t.start()
t.join()
def main():
t1 = timeit.Timer('f1()', 'from __main__ import f1')
t2 = timeit.Timer('f2()', 'from __main__ import f2')
for t in t1, t2:
print(t.repeat(3, 100))
if __name__ == '__main__':
main()
[guest@localhost threadcmp]$ ./thread_сmp3.py
[0.3606604479991802, 0.3605620809994434, 0.36211792700123624]
[1.42527558799884, 1.4459451809998427, 1.4245262650001678]
[guest@localhost threadcmp]$
из двух - да, почти та же скорость, а из трёх - в 10 раз медленнее