Lưu ý: bất cứ nơi nào tôi đề cập, thread
tôi có nghĩa là các chủ đề cụ thể trong python cho đến khi được nêu rõ ràng.
Các luồng hoạt động hơi khác trong python nếu bạn đến từ C/C++
nền. Trong python, Chỉ một luồng có thể ở trạng thái chạy tại một thời điểm nhất định, điều này có nghĩa là Các luồng trong python không thể thực sự tận dụng sức mạnh của nhiều lõi xử lý vì theo thiết kế, các luồng không thể chạy song song trên nhiều lõi.
Vì việc quản lý bộ nhớ trong python không an toàn cho luồng nên mỗi luồng yêu cầu một quyền truy cập độc quyền vào cấu trúc dữ liệu trong trình thông dịch python. Quyền truy cập độc quyền này được thực hiện bởi một cơ chế được gọi là (khóa thông dịch toàn cục) .GIL
Why does python use GIL?
Để ngăn nhiều luồng truy cập trạng thái thông dịch đồng thời và làm hỏng trạng thái thông dịch.
Ý tưởng là bất cứ khi nào một luồng đang được thực thi (ngay cả khi đó là luồng chính) , một GIL sẽ được thu thập và sau một khoảng thời gian xác định trước, GIL được giải phóng bởi luồng hiện tại và được một số luồng khác yêu cầu lại (nếu có).
Why not simply remove GIL?
Không phải là không thể loại bỏ GIL, chỉ là nếu làm như vậy một cách thận trọng, chúng ta sẽ đặt nhiều ổ khóa bên trong trình thông dịch để tuần tự hóa quyền truy cập, điều này làm cho ngay cả một ứng dụng luồng đơn lẻ cũng hoạt động kém hơn.
vì vậy chi phí loại bỏ GIL được trả bằng việc giảm hiệu suất của một ứng dụng đơn luồng, điều này không bao giờ mong muốn.
So when does thread switching occurs in python?
Chuyển đổi luồng xảy ra khi GIL được phát hành. Vậy GIL được phát hành khi nào? Có hai kịch bản cần xem xét.
Nếu một Luồng đang thực hiện các hoạt động Bound CPU (Xử lý ảnh Ex).
Trong các phiên bản cũ hơn của python, chuyển đổi Luồng được sử dụng để xảy ra sau khi không có lệnh python cố định. Theo mặc định, nó được đặt thành 100
. Hóa ra nó không phải là một chính sách rất tốt để quyết định khi nào chuyển đổi xảy ra vì thời gian thực hiện một lệnh duy nhất có thể rất nhanh từ mili giây đến thậm chí là một giây. Do đó, việc giải phóng GIL sau mỗi 100
lệnh bất kể thời gian thực thi chúng là một chính sách kém.
Trong các phiên bản mới thay vì sử dụng số lượng lệnh làm số liệu để chuyển luồng, một khoảng thời gian có thể định cấu hình được sử dụng. Khoảng thời gian chuyển đổi mặc định là 5 mili giây. Bạn có thể lấy khoảng thời gian chuyển đổi hiện tại bằng cách sử dụng sys.getswitchinterval()
. Điều này có thể được thay đổi bằng cách sử dụngsys.setswitchinterval()
Nếu một Luồng đang thực hiện một số Hoạt động liên kết IO (Truy cập hệ thống tệp Ex hoặc
IO mạng)
GIL được phát hành bất cứ khi nào luồng đang đợi một số hoạt động IO hoàn thành.
Which thread to switch to next?
Trình thông dịch không có bộ lập lịch của riêng nó. Luồng nào được lập lịch vào cuối khoảng thời gian là quyết định của hệ điều hành. .