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:

Cách tạo một widget nhập ngày và giờ sử dụng PyQt QDateTimeEdit

Cách tạo một widget nhập ngày và giờ sử dụng PyQt QDateTimeEdit

Cách tạo một widget nhập giờ sử dụng lớp PyQt QTimeEdit

Cách tạo một widget nhập giờ sử dụng lớp PyQt QTimeEdit

Cách tạo một widget nhập ngày sử dụng lớp PyQt QDateEdit

Cách tạo một widget nhập ngày sử dụng lớp PyQt QDateEdit

Cách sử dụng widget PyQt QSpinBox để tạo một spin box

Cách sử dụng widget PyQt QSpinBox để tạo một spin box

Sử dụng PyQt QComboBox để tạo Widget Combobox

Sử dụng PyQt QComboBox để tạo Widget Combobox

Cách sử dụng lớp PyQt QRadioButton

Cách sử dụng lớp PyQt QRadioButton

Cách sử dụng lớp QCheckBox trong PyQt

Cách sử dụng lớp QCheckBox trong PyQt

Cách sử dụng QFormLayout trong PyQt

Cách sử dụng QFormLayout trong PyQt

Cách sử dụng QGridLayout trong PyQt

Cách sử dụng QGridLayout trong PyQt

Cách sử dụng QVBoxLayout trong PyQt

Cách sử dụng QVBoxLayout trong PyQt

Cách sử dụng widget QLineEdit trong PyQt

Cách sử dụng widget QLineEdit trong PyQt

Cách sử dụng widget QPushButton của PyQt

Cách sử dụng widget QPushButton của PyQt

Cách sử dụng widget PyQt QLabel

Cách sử dụng widget PyQt QLabel

Tín hiệu và Khe (Signals & Slots) trong PyQt

Tín hiệu và Khe (Signals & Slots) trong PyQt

PyQt là gì? Tạo một chương trình

PyQt là gì? Tạo một chương trình "Hello World".

Ứng dụng System Tray với Tkinter

Ứng dụng System Tray với Tkinter

Cách hiển thị đồ thị từ thư viện Matplotlib trong Tkinter

Cách hiển thị đồ thị từ thư viện Matplotlib trong Tkinter

Cách sử dụng Validate trong Tkinter

Cách sử dụng Validate trong Tkinter

Cấu trúc MVC trong Tkinter

Cấu trúc MVC trong Tkinter

Cách sử dụng widget PhotoImage của Tkinter

Cách sử dụng widget PhotoImage của Tkinter

Top