Примітка: скрізь, де я згадую, thread
я маю на увазі конкретно потоки в python, поки явно не зазначено.
Потоки працюють трохи інакше в python, якщо ви походите з C/C++
фонового режиму. У python лише один потік може перебувати в робочому стані в даний момент часу. Це означає, що потоки в python не можуть по-справжньому використовувати потужність декількох обробних ядер, оскільки за проектом неможливо, щоб потоки працювали паралельно на декількох ядрах.
Оскільки управління пам'яттю в Пітоні НЕ поточно-кожен потік вимагає монопольного доступу до структур даних в Пітоні interpreter.This монопольного доступ придбаний з допомогою механізму під назвою (глобальна блокування interpretr) .GIL
Why does python use GIL?
Щоб запобігти одночасному доступу кількох потоків до стану інтерпретатора та пошкодженню стану інтерпретатора.
Ідея полягає в тому, що кожного разу, коли виконується потік (навіть якщо це основний потік) , отримується GIL, і через деякий заздалегідь визначений проміжок часу GIL звільняється поточним потоком і знову отримується якимсь іншим потоком (якщо такий є).
Why not simply remove GIL?
Це не так, що неможливо видалити GIL, просто, за умови, що це робимо, ми в кінцевому підсумку поміщаємо безліч замків всередину інтерпретатора, щоб серіалізувати доступ, що робить навіть одну різьбову програму менш ефективною.
отже, витрати на видалення GIL окупаються зменшенням продуктивності програми з одним різьбленням, що ніколи не є бажаним.
So when does thread switching occurs in python?
Перемикання потоку відбувається, коли GIL відпускається. Отже, коли GIL звільняється? Є два сценарії, які слід взяти до уваги.
Якщо Thread виконує операції, пов'язані з процесором (наприклад, обробка зображень).
У старих версіях python перемикання потоків відбувалося після фіксованого числа інструкцій python. За замовчуванням було встановлено значення 100
. Виявилося, що не дуже вдала політика приймати рішення про переключення має відбуватися з часу, затраченого на виконання однієї інструкції може дуже шалено від мілісекунд до навіть секунди. Тому випуск GIL після кожних 100
інструкцій, незалежно від часу, який вони витрачають на виконання, є поганою політикою.
У нових версіях замість того, щоб використовувати кількість інструкцій як метрику для перемикання потоку, використовується настроюваний інтервал часу. Інтервал перемикання за замовчуванням - 5 мілісекунд. Ви можете отримати поточний інтервал перемикання за допомогою sys.getswitchinterval()
. Це можна змінити за допомогоюsys.setswitchinterval()
Якщо Потік виконує певні операції з обмеженим введенням (наприклад, доступ до файлової системи або
мережевий введення-виведення)
GIL випускається кожного разу, коли потік чекає закінчення операції введення-виводу.
Which thread to switch to next?
Інтерпретатор не має власного планувальника. Який потік стає запланованим в кінці інтервалу - це рішення операційної системи. .