Thông báo: Download 4 khóa học Python từ cơ bản đến nâng cao tại đây.
Sử dụng Semaphore trong Python
Trong bài viết này, bạn sẽ học cách sử dụng Semaphore trong Python để kiểm soát số lượng luồng có thể truy cập vào một tài nguyên chia sẻ cùng lúc. Semaphore là một công cụ đồng bộ hóa mạnh mẽ giúp ngăn chặn các vấn đề đồng thời như race conditions, nơi mà nhiều luồng cố gắng truy cập vào tài nguyên cùng một lúc và gây ra sự cố. Bằng cách sử dụng Semaphore, bạn có thể đảm bảo rằng một số lượng giới hạn các luồng có thể truy cập vào tài nguyên chia sẻ, giúp tăng tính ổn định và an toàn cho ứng dụng của bạn.
Giới thiệu về Semaphore trong Python
Semaphore trong Python là một công cụ đồng bộ hóa cho phép bạn kiểm soát truy cập vào một tài nguyên chia sẻ. Về cơ bản, Semaphore là một bộ đếm kèm theo một khóa, giới hạn số lượng luồng có thể truy cập vào tài nguyên chia sẻ cùng một lúc.
Semaphore giúp ngăn chặn các vấn đề đồng bộ hóa luồng như race condition, nơi mà nhiều luồng cố gắng truy cập vào tài nguyên cùng một lúc và làm ảnh hưởng lẫn nhau.
Semaphore duy trì một bộ đếm. Khi một luồng muốn truy cập tài nguyên chia sẻ, semaphore sẽ kiểm tra bộ đếm. Nếu bộ đếm lớn hơn 0, nó sẽ giảm bộ đếm và cho phép luồng truy cập tài nguyên. Nếu bộ đếm bằng 0, semaphore sẽ chặn luồng cho đến khi bộ đếm lớn hơn 0.
Bài viết này được đăng tại [free tuts .net]
Semaphore có hai thao tác chính:
Acquire
: Thao tác này kiểm tra bộ đếm và giảm nó nếu lớn hơn 0. Nếu bộ đếm bằng 0, semaphore sẽ chặn luồng cho đến khi một luồng khác giải phóng semaphore.Release
: Thao tác này tăng bộ đếm, cho phép các luồng khác có thể acquire nó.
Sử dụng Semaphore trong Python
Để sử dụng semaphore, bạn thực hiện các bước sau:
- Đầu tiên, import mô-đun threading:
import threading
- Tạo một đối tượng Semaphore và xác định số lượng luồng có thể acquire cùng lúc:
semaphore = threading.Semaphore(3)
Trong ví dụ này, chúng ta tạo một đối tượng Semaphore chỉ cho phép tối đa ba luồng acquire cùng lúc.
- Acquire semaphore từ một luồng bằng cách gọi phương thức
acquire()
:
semaphore.acquire()
Nếu bộ đếm semaphore bằng 0, luồng sẽ đợi cho đến khi một luồng khác giải phóng semaphore. Khi đã acquire semaphore, bạn có thể thực hiện một phần mã quan trọng.
-
Giải phóng semaphore sau khi chạy xong phần mã quan trọng bằng cách gọi phương thức
release()
:
semaphore.release()
Để đảm bảo semaphore được acquire và release một cách chính xác, ngay cả khi có ngoại lệ xảy ra trong quá trình chạy phần mã quan trọng, bạn có thể sử dụng câu lệnh with
:
with semaphore: # Mã trong khối này đã acquire semaphore # Thực hiện các thao tác trên tài nguyên chia sẻ # ... # Semaphore được release ngoài khối with
Ví dụ về sử dụng Semaphore trong Python
Ví dụ sau đây minh họa cách sử dụng semaphore để giới hạn số lượng tải xuống đồng thời tối đa là ba bằng cách sử dụng multithreading trong Python:
import threading import urllib.request MAX_CONCURRENT_DOWNLOADS = 3 semaphore = threading.Semaphore(MAX_CONCURRENT_DOWNLOADS) def download(url): with semaphore: print(f"Downloading {url}...") response = urllib.request.urlopen(url) data = response.read() print(f"Finished downloading {url}") return data def main(): urls = [ 'https://www.ietf.org/rfc/rfc791.txt', 'https://www.ietf.org/rfc/rfc792.txt', 'https://www.ietf.org/rfc/rfc793.txt', 'https://www.ietf.org/rfc/rfc794.txt', 'https://www.ietf.org/rfc/rfc795.txt', ] threads = [] for url in urls: thread = threading.Thread(target=download, args=(url,)) threads.append(thread) thread.start() for thread in threads: thread.join() if __name__ == '__main__': main()
Kết quả:
Downloading https://www.ietf.org/rfc/rfc791.txt... Downloading https://www.ietf.org/rfc/rfc792.txt... Downloading https://www.ietf.org/rfc/rfc793.txt... Finished downloading https://www.ietf.org/rfc/rfc792.txt Downloading https://www.ietf.org/rfc/rfc794.txt... Finished downloading https://www.ietf.org/rfc/rfc791.txt Downloading https://www.ietf.org/rfc/rfc795.txt... Finished downloading https://www.ietf.org/rfc/rfc793.txt Finished downloading https://www.ietf.org/rfc/rfc794.txt Finished downloading https://www.ietf.org/rfc/rfc795.txt
Kết quả này cho thấy chỉ tối đa ba luồng có thể tải xuống cùng lúc:
Downloading https://www.ietf.org/rfc/rfc791.txt... Downloading https://www.ietf.org/rfc/rfc792.txt... Downloading https://www.ietf.org/rfc/rfc793.txt...
Khi số lượng luồng đạt tới ba, luồng tiếp theo phải đợi semaphore được giải phóng bởi một luồng khác.
Ví dụ, luồng #2 hoàn thành và giải phóng semaphore, và luồng tiếp theo bắt đầu tải xuống URL https://www.ietf.org/rfc/rfc794.txt
:
Finished downloading https://www.ietf.org/rfc/rfc792.txt Downloading https://www.ietf.org/rfc/rfc794.txt...
Kết bài
Sử dụng semaphore trong Python để kiểm soát số lượng luồng có thể truy cập vào một tài nguyên chia sẻ cùng lúc giúp ngăn chặn các vấn đề đồng bộ hóa và đảm bảo an toàn cho các hoạt động trên tài nguyên chia sẻ. Bằng cách sử dụng các phương thức acquire() và release(), bạn có thể quản lý truy cập vào tài nguyên một cách hiệu quả và tránh các vấn đề như race conditions. Hy vọng rằng qua bài viết này, bạn đã hiểu rõ hơn về cách sử dụng semaphore trong Python để xây dựng các ứng dụng đa luồng an toàn và đáng tin cậy.