Ví dụ về đa luồng trong Python với Khóa thông dịch toàn cầu (GIL)

Mục lục:

Anonim

Ngôn ngữ lập trình python cho phép bạn sử dụng đa xử lý hoặc đa luồng. Trong hướng dẫn này, bạn sẽ học cách viết các ứng dụng đa luồng bằng Python.

Chủ đề là gì?

Một luồng là một đơn vị ngoại trừ trên lập trình đồng thời. Đa luồng là một kỹ thuật cho phép CPU thực hiện nhiều tác vụ của một tiến trình cùng một lúc. Các luồng này có thể thực thi riêng lẻ trong khi chia sẻ tài nguyên quy trình của chúng.

Quy trình là gì?

Một tiến trình về cơ bản là chương trình đang được thực thi. Khi bạn khởi động một ứng dụng trong máy tính của mình (như trình duyệt hoặc trình soạn thảo văn bản), hệ điều hành sẽ tạo ra một quy trình.

Đa luồng trong Python là gì?

Đa luồng trong lập trình Python là một kỹ thuật nổi tiếng trong đó nhiều luồng trong một quy trình chia sẻ không gian dữ liệu của chúng với luồng chính, giúp chia sẻ thông tin và giao tiếp trong các luồng dễ dàng và hiệu quả. Chủ đề nhẹ hơn quy trình. Nhiều luồng có thể thực thi riêng lẻ trong khi chia sẻ tài nguyên quy trình của chúng. Mục đích của đa luồng là chạy nhiều tác vụ và các ô chức năng cùng một lúc.

Multiprocessing là gì?

Đa xử lý cho phép bạn chạy đồng thời nhiều quy trình không liên quan. Các quy trình này không chia sẻ tài nguyên của chúng và giao tiếp thông qua IPC.

Đa luồng trong Python so với Đa xử lý

Để hiểu các quy trình và chuỗi, hãy xem xét tình huống này: Tệp .exe trên máy tính của bạn là một chương trình. Khi bạn mở nó, hệ điều hành sẽ tải nó vào bộ nhớ và CPU sẽ thực thi nó. Phiên bản của chương trình hiện đang chạy được gọi là tiến trình.

Mọi quy trình sẽ có 2 thành phần cơ bản:

  • Mật mã
  • Dữ liệu

Bây giờ, một tiến trình có thể chứa một hoặc nhiều phần con được gọi là luồng. Điều này phụ thuộc vào kiến ​​trúc hệ điều hành, bạn có thể nghĩ về một luồng như một phần của quy trình có thể được thực thi riêng bởi hệ điều hành.

Nói cách khác, nó là một dòng hướng dẫn có thể được chạy độc lập bởi hệ điều hành. Các luồng trong một quy trình duy nhất chia sẻ dữ liệu của quy trình đó và được thiết kế để hoạt động cùng nhau nhằm tạo điều kiện thuận lợi cho quá trình song song.

Trong hướng dẫn này, bạn sẽ học,

  • Chủ đề là gì?
  • Quy trình là gì?
  • Đa luồng là gì?
  • Multiprocessing là gì?
  • Đa luồng trong Python so với Đa xử lý
  • Tại sao sử dụng Đa luồng?
  • Đa luồng trong Python
  • Các mô-đun Threading và Threading
  • Mô-đun chủ đề
  • Mô-đun phân luồng
  • Bế tắc và điều kiện cuộc đua
  • Đồng bộ hóa chuỗi
  • GIL là gì?
  • Tại sao cần GIL?

Tại sao sử dụng Đa luồng?

Đa luồng cho phép bạn chia một ứng dụng thành nhiều tác vụ con và chạy các tác vụ này đồng thời. Nếu bạn sử dụng đa luồng đúng cách, tốc độ, hiệu suất và kết xuất ứng dụng của bạn đều có thể được cải thiện.

Đa luồng trong Python

Python hỗ trợ các cấu trúc cho cả quá trình đa xử lý cũng như đa luồng. Trong hướng dẫn này, bạn sẽ chủ yếu tập trung vào việc triển khai các ứng dụng đa luồng với python. Có hai mô-đun chính có thể được sử dụng để xử lý các luồng trong Python:

  1. Các chủ đề mô-đun, và
  2. Các luồng mô-đun

Tuy nhiên, trong python, cũng có một thứ gọi là khóa thông dịch toàn cục (GIL). Nó không cho phép tăng nhiều hiệu suất và thậm chí có thể làm giảm hiệu suất của một số ứng dụng đa luồng. Bạn sẽ tìm hiểu tất cả về nó trong các phần sắp tới của hướng dẫn này.

Các mô-đun Threading và Threading

Hai module mà bạn sẽ tìm hiểu về trong hướng dẫn này là mô-đun chủ đề và các mô-đun threading .

Tuy nhiên, mô-đun luồng từ lâu đã không được dùng nữa. Bắt đầu với Python 3, nó đã được chỉ định là lỗi thời và chỉ có thể truy cập dưới dạng __thread để tương thích ngược.

Bạn nên sử dụng mô-đun phân luồng cấp cao hơn cho các ứng dụng mà bạn định triển khai. Mô-đun chủ đề chỉ được đề cập ở đây cho mục đích giáo dục.

Mô-đun chủ đề

Cú pháp để tạo một luồng mới bằng cách sử dụng mô-đun này như sau:

thread.start_new_thread(function_name, arguments)

Được rồi, bây giờ bạn đã nắm được lý thuyết cơ bản để bắt đầu viết mã. Vì vậy, hãy mở IDLE hoặc sổ ghi chú của bạn và nhập thông tin sau:

import timeimport _threaddef thread_test(name, wait):i = 0while i <= 3:time.sleep(wait)print("Running %s\n" %name)i = i + 1print("%s has finished execution" %name)if __name__ == "__main__":_thread.start_new_thread(thread_test, ("First Thread", 1))_thread.start_new_thread(thread_test, ("Second Thread", 2))_thread.start_new_thread(thread_test, ("Third Thread", 3))

Lưu tệp và nhấn F5 để chạy chương trình. Nếu mọi thứ được thực hiện chính xác, đây là kết quả mà bạn sẽ thấy:

Bạn sẽ tìm hiểu thêm về điều kiện cuộc đua và cách xử lý chúng trong các phần sắp tới

GIẢI THÍCH MÃ

  1. Các câu lệnh này nhập thời gian và mô-đun luồng được sử dụng để xử lý việc thực thi và trì hoãn các luồng Python.
  2. Ở đây, bạn đã xác định một hàm có tên là thread_test, hàm này sẽ được gọi bởi phương thức start_new_thread . Hàm chạy một vòng lặp while trong bốn lần lặp và in ra tên của luồng đã gọi nó. Khi quá trình lặp lại hoàn tất, nó sẽ in ra một thông báo cho biết rằng luồng đã hoàn tất quá trình thực thi.
  3. Đây là phần chính của chương trình của bạn. Ở đây, bạn chỉ cần gọi phương thức start_new_thread với hàm thread_test làm đối số.

    Thao tác này sẽ tạo một luồng mới cho hàm mà bạn truyền làm đối số và bắt đầu thực thi nó. Lưu ý rằng bạn có thể thay thế chức năng này (luồng _ kiểm tra) bằng bất kỳ chức năng nào khác mà bạn muốn chạy dưới dạng một luồng.

Mô-đun phân luồng

Mô-đun này là triển khai cấp cao của phân luồng trong python và tiêu chuẩn thực tế để quản lý các ứng dụng đa luồng. Nó cung cấp một loạt các tính năng khi so sánh với mô-đun luồng.

Cấu trúc của mô-đun Threading

Dưới đây là danh sách một số chức năng hữu ích được xác định trong mô-đun này:

Tên chức năng Sự miêu tả
activeCount () Trả về số lượng các đối tượng Thread vẫn còn sống
currentThread () Trả về đối tượng hiện tại của lớp Thread.
liệt kê () Liệt kê tất cả các đối tượng Thread đang hoạt động.
isDaemon () Trả về true nếu luồng là daemon.
isAlive () Trả về true nếu luồng vẫn còn sống.
Phương thức lớp chủ đề
khởi đầu() Bắt đầu hoạt động của một chủ đề. Nó chỉ được gọi một lần cho mỗi luồng vì nó sẽ gây ra lỗi thời gian chạy nếu được gọi nhiều lần.
chạy() Phương thức này biểu thị hoạt động của một luồng và có thể bị ghi đè bởi một lớp mở rộng lớp Luồng.
tham gia() Nó chặn việc thực thi mã khác cho đến khi kết thúc chuỗi mà phương thức join () được gọi.

Cốt truyện: Lớp Chủ đề

Trước khi bạn bắt đầu viết mã các chương trình đa luồng bằng cách sử dụng mô-đun luồng, điều quan trọng là phải hiểu về lớp Luồng. Lớp luồng là lớp chính định nghĩa khuôn mẫu và các hoạt động của một luồng trong python.

Cách phổ biến nhất để tạo một ứng dụng python đa luồng là khai báo một lớp mở rộng lớp Thread và ghi đè phương thức run () của nó.

Tóm lại, lớp Thread biểu thị một chuỗi mã chạy trong một luồng điều khiển riêng biệt .

Vì vậy, khi viết một ứng dụng đa luồng, bạn sẽ làm như sau:

  1. định nghĩa một lớp mở rộng lớp Thread
  2. Ghi đè __init__ constructor
  3. Ghi đè phương thức run ()

Khi một đối tượng luồng đã được tạo, phương thức start () có thể được sử dụng để bắt đầu thực thi hoạt động này và phương thức join () có thể được sử dụng để chặn tất cả các mã khác cho đến khi hoạt động hiện tại kết thúc.

Bây giờ, hãy thử sử dụng mô-đun luồng để triển khai ví dụ trước của bạn. Một lần nữa, kích hoạt IDLE của bạn và nhập thông tin sau:

import timeimport threadingclass threadtester (threading.Thread):def __init__(self, id, name, i):threading.Thread.__init__(self)self.id = idself.name = nameself.i = idef run(self):thread_test(self.name, self.i, 5)print ("%s has finished execution " %self.name)def thread_test(name, wait, i):while i:time.sleep(wait)print ("Running %s \n" %name)i = i - 1if __name__=="__main__":thread1 = threadtester(1, "First Thread", 1)thread2 = threadtester(2, "Second Thread", 2)thread3 = threadtester(3, "Third Thread", 3)thread1.start()thread2.start()thread3.start()thread1.join()thread2.join()thread3.join()

Đây sẽ là đầu ra khi bạn thực thi đoạn mã trên:

GIẢI THÍCH MÃ

  1. Phần này giống với ví dụ trước của chúng tôi. Tại đây, bạn nhập thời gian và mô-đun luồng được sử dụng để xử lý việc thực thi và độ trễ của các luồng Python.
  2. Trong bit này, bạn đang tạo một lớp có tên là threadtester, lớp này kế thừa hoặc mở rộng lớp Thread của mô-đun luồng. Đây là một trong những cách phổ biến nhất để tạo luồng trong python. Tuy nhiên, bạn chỉ nên ghi đè phương thức khởi tạo và phương thức run () trong ứng dụng của mình. Như bạn có thể thấy trong mẫu mã ở trên, phương thức __init__ (hàm tạo) đã bị ghi đè.

    Tương tự, bạn cũng đã ghi đè phương thức run () . Nó chứa mã mà bạn muốn thực thi bên trong một luồng. Trong ví dụ này, bạn đã gọi hàm thread_test ().

  3. Đây là phương thức thread_test () lấy giá trị của i làm đối số, giảm nó đi 1 ở mỗi lần lặp và lặp qua phần còn lại của mã cho đến khi tôi trở thành 0. Trong mỗi lần lặp, nó in ra tên của chuỗi hiện đang thực thi. và ngủ trong giây chờ đợi (cũng được coi là một đối số).
  4. thread1 = threadtester (1, "Chủ đề đầu tiên", 1)

    Ở đây, chúng tôi đang tạo một luồng và truyền ba tham số mà chúng tôi đã khai báo trong __init__. Tham số đầu tiên là id của luồng, tham số thứ hai là tên của luồng và tham số thứ ba là bộ đếm, xác định số lần vòng lặp while sẽ chạy.

  5. thread2.start ()

    Phương thức start được sử dụng để bắt đầu thực thi một luồng. Bên trong, hàm start () gọi phương thức run () của lớp bạn.

  6. thread3.join ()

    Phương thức join () chặn việc thực thi mã khác và đợi cho đến khi luồng mà nó được gọi là kết thúc.

Như bạn đã biết, các luồng trong cùng một quy trình có quyền truy cập vào bộ nhớ và dữ liệu của quy trình đó. Do đó, nếu nhiều luồng cố gắng thay đổi hoặc truy cập dữ liệu đồng thời, lỗi có thể xuất hiện.

Trong phần tiếp theo, bạn sẽ thấy các loại phức tạp khác nhau có thể xuất hiện khi các luồng truy cập vào dữ liệu và phần quan trọng mà không cần kiểm tra các giao dịch truy cập hiện có.

Bế tắc và điều kiện cuộc đua

Trước khi tìm hiểu về deadlock và điều kiện đua, sẽ rất hữu ích nếu bạn hiểu một vài định nghĩa cơ bản liên quan đến lập trình đồng thời:

  • Phần quan trọng

    Nó là một đoạn mã truy cập hoặc sửa đổi các biến được chia sẻ và phải được thực hiện như một giao dịch nguyên tử.

  • Chuyển đổi nội dung

    Nó là quá trình CPU tuân theo để lưu trữ trạng thái của một luồng trước khi thay đổi từ tác vụ này sang tác vụ khác để có thể tiếp tục lại từ cùng một điểm sau đó.

Bế tắc

Bế tắc là vấn đề đáng sợ nhất mà các nhà phát triển phải đối mặt khi viết các ứng dụng đồng thời / đa luồng trong python. Cách tốt nhất để hiểu các bế tắc là sử dụng bài toán ví dụ khoa học máy tính cổ điển được gọi là Bài toán triết học ăn uống.

Câu hỏi đặt ra cho các triết gia ăn uống như sau:

Năm triết gia ngồi trên một chiếc bàn tròn với năm đĩa mỳ Ý (một loại mì ống) và năm chiếc nĩa, như trong sơ đồ.

Vấn đề triết học ăn uống

Tại bất kỳ thời điểm nào, một triết gia phải đang ăn hoặc đang suy nghĩ.

Hơn nữa, một triết gia phải lấy hai chiếc nĩa liền kề với mình (tức là nĩa bên trái và bên phải) trước khi anh ta có thể ăn mì spaghetti. Vấn đề bế tắc xảy ra khi cả năm nhà triết học chọn những ngã rẽ bên phải của họ cùng một lúc.

Vì mỗi nhà triết học có một cái nĩa, nên tất cả họ sẽ đợi những người khác đặt cái nĩa của họ. Kết quả là, không ai trong số họ sẽ có thể ăn spaghetti.

Tương tự, trong một hệ thống đồng thời, một sự bế tắc xảy ra khi các luồng hoặc quy trình khác nhau (các triết gia) cố gắng lấy các tài nguyên hệ thống được chia sẻ (các nhánh) cùng một lúc. Kết quả là không có quy trình nào có cơ hội thực thi vì chúng đang chờ một tài nguyên khác do một quy trình khác nắm giữ.

Điều kiện cuộc đua

Điều kiện chạy đua là trạng thái không mong muốn của chương trình xảy ra khi hệ thống thực hiện đồng thời hai hoặc nhiều hoạt động. Ví dụ, hãy xem xét vòng lặp for đơn giản này:

i=0; # a global variablefor x in range(100):print(i)i+=1;

Nếu bạn tạo n số luồng chạy mã này cùng một lúc, bạn không thể xác định giá trị của i (được chia sẻ bởi các luồng) khi chương trình kết thúc thực thi. Điều này là do trong môi trường đa luồng thực, các luồng có thể chồng chéo lên nhau và giá trị của i được một luồng truy xuất và sửa đổi có thể thay đổi giữa khi một số luồng khác truy cập vào nó.

Đây là hai lớp vấn đề chính có thể xảy ra trong ứng dụng python đa luồng hoặc phân tán. Trong phần tiếp theo, bạn sẽ tìm hiểu cách khắc phục vấn đề này bằng cách đồng bộ hóa các luồng.

Đồng bộ hóa chuỗi

Để đối phó với các điều kiện chủng tộc, bế tắc và các vấn đề dựa trên luồng khác, mô-đun phân luồng cung cấp đối tượng Khóa . Ý tưởng là khi một luồng muốn truy cập vào một tài nguyên cụ thể, nó sẽ có được một khóa cho tài nguyên đó. Khi một luồng khóa một tài nguyên cụ thể, không một luồng nào khác có thể truy cập nó cho đến khi khóa được giải phóng. Do đó, các thay đổi đối với tài nguyên sẽ là nguyên tử và các điều kiện chủng tộc sẽ bị hủy bỏ.

Khóa là một nguyên thủy đồng bộ hóa mức thấp được thực thi bởi mô-đun __thread . Tại bất kỳ thời điểm nào, khóa có thể ở một trong 2 trạng thái: khóa hoặc mở khóa. Nó hỗ trợ hai phương pháp:

  1. có được, thu được()

    Khi trạng thái khóa được mở khóa, việc gọi phương thức get () sẽ thay đổi trạng thái thành bị khóa và quay trở lại. Tuy nhiên, Nếu trạng thái bị khóa, lệnh gọi để thu được () sẽ bị chặn cho đến khi phương thức release () được gọi bởi một số luồng khác.

  2. giải phóng()

    Phương thức release () được sử dụng để thiết lập trạng thái mở khóa, tức là để phát hành khóa. Nó có thể được gọi bởi bất kỳ luồng nào, không nhất thiết phải là luồng đã có được khóa.

Đây là một ví dụ về việc sử dụng khóa trong ứng dụng của bạn. Kích hoạt IDLE của bạn và nhập thông tin sau:

import threadinglock = threading.Lock()def first_function():for i in range(5):lock.acquire()print ('lock acquired')print ('Executing the first funcion')lock.release()def second_function():for i in range(5):lock.acquire()print ('lock acquired')print ('Executing the second funcion')lock.release()if __name__=="__main__":thread_one = threading.Thread(target=first_function)thread_two = threading.Thread(target=second_function)thread_one.start()thread_two.start()thread_one.join()thread_two.join()

Bây giờ, nhấn F5. Bạn sẽ thấy một đầu ra như thế này:

GIẢI THÍCH MÃ

  1. Ở đây, bạn chỉ cần tạo một khóa mới bằng cách gọi hàm nhà máy threading.Lock () . Bên trong, Lock () trả về một phiên bản của lớp Lock cụ thể hiệu quả nhất được nền tảng duy trì.
  2. Trong câu lệnh đầu tiên, bạn có được khóa bằng cách gọi phương thức get (). Khi khóa đã được cấp, bạn in "khóa có được" vào bảng điều khiển. Khi tất cả mã mà bạn muốn luồng chạy đã hoàn tất quá trình thực thi, bạn giải phóng khóa bằng cách gọi phương thức release ().

Về lý thuyết thì ổn, nhưng làm thế nào để bạn biết rằng khóa thực sự hoạt động? Nếu bạn nhìn vào đầu ra, bạn sẽ thấy rằng mỗi câu lệnh in đang in chính xác một dòng tại một thời điểm. Nhớ lại rằng, trong một ví dụ trước đó, các kết quả đầu ra từ print gặp rắc rối vì nhiều luồng đang truy cập phương thức print () cùng một lúc. Ở đây, chức năng in chỉ được gọi sau khi khóa được mua. Vì vậy, các kết quả đầu ra được hiển thị lần lượt và từng dòng một.

Ngoài khóa, python cũng hỗ trợ một số cơ chế khác để xử lý đồng bộ hóa luồng như được liệt kê bên dưới:

  1. RLocks
  2. Semaphores
  3. Điều kiện
  4. Sự kiện và
  5. Rào cản

Khóa thông dịch viên toàn cầu (và cách đối phó với nó)

Trước khi đi vào chi tiết về GIL của python, hãy xác định một số thuật ngữ sẽ hữu ích trong việc hiểu phần sắp tới:

  1. Mã ràng buộc CPU: điều này đề cập đến bất kỳ đoạn mã nào sẽ được thực thi trực tiếp bởi CPU.
  2. Mã ràng buộc I / O: đây có thể là bất kỳ mã nào truy cập vào hệ thống tệp thông qua 'Hệ điều hành
  3. CPython: nó là triển khai tham chiếu của Python và có thể được mô tả như trình thông dịch được viết bằng C và Python (ngôn ngữ lập trình).

GIL trong Python là gì?

Khóa thông dịch viên toàn cầu (GIL) trong python là một khóa quy trình hoặc một mutex được sử dụng trong khi xử lý các quy trình. Nó đảm bảo rằng một luồng có thể truy cập một tài nguyên cụ thể tại một thời điểm và nó cũng ngăn việc sử dụng các đối tượng và mã byte cùng một lúc. Điều này có lợi cho các chương trình đơn luồng trong việc tăng hiệu suất. GIL trong python rất đơn giản và dễ thực hiện.

Một khóa có thể được sử dụng để đảm bảo rằng chỉ một luồng có quyền truy cập vào một tài nguyên cụ thể tại một thời điểm nhất định.

Một trong những tính năng của Python là nó sử dụng khóa toàn cục trên mỗi quy trình thông dịch, có nghĩa là mọi quy trình đều coi chính trình thông dịch python như một tài nguyên.

Ví dụ: giả sử bạn đã viết một chương trình python sử dụng hai luồng để thực hiện cả hoạt động của CPU và 'I / O'. Khi bạn thực thi chương trình này, đây là những gì sẽ xảy ra:

  1. Trình thông dịch python tạo một quy trình mới và tạo ra các chuỗi
  2. Khi luồng-1 bắt đầu chạy, trước tiên nó sẽ nhận GIL và khóa nó.
  3. Nếu luồng-2 muốn thực thi ngay bây giờ, nó sẽ phải đợi GIL được giải phóng ngay cả khi một bộ xử lý khác miễn phí.
  4. Bây giờ, giả sử luồng-1 đang chờ thao tác I / O. Tại thời điểm này, nó sẽ giải phóng GIL và luồng-2 sẽ có được nó.
  5. Sau khi hoàn thành các hoạt động I / O, nếu luồng-1 muốn thực thi ngay bây giờ, nó sẽ lại phải đợi GIL được luồng-2 giải phóng.

Do đó, chỉ một luồng có thể truy cập trình thông dịch bất kỳ lúc nào, có nghĩa là sẽ chỉ có một luồng thực thi mã python tại một thời điểm nhất định.

Điều này không sao cả trong bộ xử lý lõi đơn vì nó sẽ sử dụng phương pháp cắt thời gian (xem phần đầu tiên của hướng dẫn này) để xử lý các luồng. Tuy nhiên, trong trường hợp bộ xử lý đa lõi, một chức năng ràng buộc CPU thực thi trên nhiều luồng sẽ có tác động đáng kể đến hiệu quả của chương trình vì nó sẽ không thực sự sử dụng tất cả các lõi có sẵn cùng một lúc.

Tại sao cần GIL?

Bộ thu gom rác CPython sử dụng một kỹ thuật quản lý bộ nhớ hiệu quả được gọi là đếm tham chiếu. Đây là cách hoạt động: Mọi đối tượng trong python đều có số lượng tham chiếu, số này sẽ tăng lên khi nó được gán cho một tên biến mới hoặc được thêm vào vùng chứa (như bộ giá trị, danh sách, v.v.). Tương tự như vậy, số lượng tham chiếu bị giảm khi tham chiếu vượt ra ngoài phạm vi hoặc khi lệnh del được gọi. Khi số lượng tham chiếu của một đối tượng đạt đến 0, nó sẽ được thu thập rác và bộ nhớ được phân bổ sẽ được giải phóng.

Nhưng vấn đề là biến đếm tham chiếu có xu hướng gặp phải các điều kiện chạy đua giống như bất kỳ biến toàn cục nào khác. Để giải quyết vấn đề này, các nhà phát triển python đã quyết định sử dụng khóa thông dịch toàn cục. Tùy chọn khác là thêm một khóa cho mỗi đối tượng, điều này có thể dẫn đến bế tắc và tăng chi phí từ các lệnh gọi get () và release ().

Do đó, GIL là một hạn chế đáng kể đối với các chương trình python đa luồng chạy các hoạt động ràng buộc CPU nặng (làm cho chúng trở nên đơn luồng một cách hiệu quả). Nếu bạn muốn sử dụng nhiều lõi CPU trong ứng dụng của mình, hãy sử dụng mô-đun đa xử lý .

Tóm lược

  • Python hỗ trợ 2 mô-đun cho đa luồng:
    1. __thread module: Nó cung cấp một triển khai cấp thấp cho luồng và đã lỗi thời.
    2. mô-đun phân luồng : Nó cung cấp một triển khai cấp cao cho đa luồng và là tiêu chuẩn hiện tại.
  • Để tạo một luồng bằng mô-đun luồng, bạn phải làm như sau:
    1. Tạo một lớp mở rộng lớp Thread .
    2. Ghi đè phương thức khởi tạo của nó (__init__).
    3. Ghi đè phương thức run () của nó .
    4. Tạo một đối tượng của lớp này.
  • Một luồng có thể được thực thi bằng cách gọi phương thức start () .
  • Phương thức join () có thể được sử dụng để chặn các luồng khác cho đến khi luồng này (luồng mà phép nối được gọi) kết thúc quá trình thực thi.
  • Điều kiện chạy đua xảy ra khi nhiều luồng truy cập hoặc sửa đổi tài nguyên được chia sẻ cùng một lúc.
  • Nó có thể tránh được bằng cách Đồng bộ hóa các luồng.
  • Python hỗ trợ 6 cách để đồng bộ hóa các luồng:
    1. Ổ khóa
    2. RLocks
    3. Semaphores
    4. Điều kiện
    5. Sự kiện và
    6. Rào cản
  • Các khóa chỉ cho phép một chủ đề cụ thể đã có được khóa để vào phần quan trọng.
  • A Lock có 2 phương thức chính:
    1. get () : Nó đặt trạng thái khóa thành bị khóa. Nếu được gọi trên một đối tượng bị khóa, nó sẽ chặn cho đến khi tài nguyên được giải phóng.
    2. release () : Nó đặt trạng thái khóa thành mở khóa và trả về. Nếu được gọi trên một đối tượng đã mở khóa, nó sẽ trả về false.
  • Khóa thông dịch viên toàn cục là một cơ chế mà qua đó chỉ có 1 quy trình thông dịch CPython có thể thực thi tại một thời điểm.
  • Nó được sử dụng để hỗ trợ chức năng đếm tham chiếu của bộ thu gom rác của CPythons.
  • Để tạo các ứng dụng Python với các hoạt động ràng buộc CPU nặng, bạn nên sử dụng mô-đun đa xử lý.