PYTHON CONCURRENCY
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
MỚI CẬP NHẬT

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.

test php

banquyen png
Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

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.

Cùng chuyên mục:

Hướng dẫn xây dựng Command-Line Interface (CLI) bằng Quo trong Python

Hướng dẫn xây dựng Command-Line Interface (CLI) bằng Quo trong Python

Hướng dẫn toàn diện về module datetime trong Python

Hướng dẫn toàn diện về module datetime trong Python

Cách truy cập và thiết lập biến môi trường trong Python

Cách truy cập và thiết lập biến môi trường trong Python

Lớp dữ liệu (Data Classes) trong Python với decorator @dataclass

Lớp dữ liệu (Data Classes) trong Python với decorator @dataclass

Từ khóa yield trong Python

Từ khóa yield trong Python

Sự khác biệt giữa sort() và sorted() trong Python

Sự khác biệt giữa sort() và sorted() trong Python

Sử dụng Poetry để quản lý dependencies trong Python

Sử dụng Poetry để quản lý dependencies trong Python

Định dạng chuỗi Strings trong Python

Định dạng chuỗi Strings trong Python

Một tác vụ phổ biến khi làm việc với danh sách trong Python

Một tác vụ phổ biến khi làm việc với danh sách trong Python

Làm việc với các biến môi trường trong Python

Làm việc với các biến môi trường trong Python

Sự khác biệt giữa set() và frozenset() trong Python

Sự khác biệt giữa set() và frozenset() trong Python

Sự khác biệt giữa iterator và iterable trong Python

Sự khác biệt giữa iterator và iterable trong Python

Cách làm việc với file tarball/tar trong Python

Cách làm việc với file tarball/tar trong Python

Chuyển đổi kiểu dữ liệu trong Python

Chuyển đổi kiểu dữ liệu trong Python

Sự khác biệt giữa toán tử == và is trong Python

Sự khác biệt giữa toán tử == và is trong Python

Làm việc với file ZIP trong Python

Làm việc với file ZIP trong Python

Cách sử dụng ThreadPoolExecutor trong Python

Cách sử dụng ThreadPoolExecutor trong Python

Sự khác biệt giữa byte objects và string trong Python

Sự khác biệt giữa byte objects và string trong Python

Xử lý độ chính xác các hàm floor, ceil, round, trunc, format  trong Python

Xử lý độ chính xác các hàm floor, ceil, round, trunc, format trong Python

Cách lặp qua nhiều list với hàm zip() trong Python

Cách lặp qua nhiều list với hàm zip() trong Python

Top