Khóa học python

Giới thiệu về Multithreading trong Python

0 phút đọc

Multithreading là một kỹ thuật lập trình cho phép thực thi nhiều luồng (threads) đồng thời trong một chương trình. Mỗi luồng là một đơn vị thực thi độc lập, có thể chạy song song với các luồng khác. Multithreading giúp cải thiện hiệu suất và khả năng đáp ứng của ứng dụng, đặc biệt là trong các tác vụ I/O-bound như đọc/ghi file, truy cập mạng, và giao tiếp với cơ sở dữ liệu.

Tại sao sử dụng Multithreading?

  • Cải thiện hiệu suất: Multithreading cho phép thực thi nhiều tác vụ đồng thời, giúp tận dụng tối đa tài nguyên của hệ thống.
  • Tăng khả năng đáp ứng: Các ứng dụng đa luồng có thể xử lý nhiều yêu cầu cùng lúc, giúp tăng khả năng đáp ứng và giảm thời gian chờ đợi của người dùng.
  • Đơn giản hóa thiết kế: Multithreading giúp chia nhỏ các tác vụ phức tạp thành các luồng độc lập, làm cho mã nguồn dễ hiểu và dễ bảo trì hơn.

Multithreading trong Python

Python cung cấp module threading để hỗ trợ lập trình đa luồng. Module này cung cấp các lớp và hàm để tạo và quản lý các luồng trong Python.

Tạo và quản lý luồng

Tạo luồng bằng cách kế thừa lớp Thread

Bạn có thể tạo một luồng mới bằng cách kế thừa lớp Thread và ghi đè phương thức run().

Ví dụ:

python Copy
import threading
import time

class MyThread(threading.Thread):
    def __init__(self, name):
        threading.Thread.__init__(self)
        self.name = name

    def run(self):
        print(f"Starting {self.name}")
        time.sleep(2)
        print(f"Exiting {self.name}")

# Tạo và khởi động các luồng
thread1 = MyThread("Thread-1")
thread2 = MyThread("Thread-2")

thread1.start()
thread2.start()

thread1.join()
thread2.join()

print("Exiting Main Thread")

Kết quả:

Copy
Starting Thread-1
Starting Thread-2
Exiting Thread-1
Exiting Thread-2
Exiting Main Thread

Tạo luồng bằng cách sử dụng hàm Thread()

Bạn cũng có thể tạo một luồng mới bằng cách sử dụng hàm Thread() và truyền vào một hàm hoặc phương thức để thực thi.

Ví dụ:

python Copy
import threading
import time

def print_time(thread_name, delay):
    print(f"Starting {thread_name}")
    time.sleep(delay)
    print(f"Exiting {thread_name}")

# Tạo và khởi động các luồng
thread1 = threading.Thread(target=print_time, args=("Thread-1", 2))
thread2 = threading.Thread(target=print_time, args=("Thread-2", 2))

thread1.start()
thread2.start()

thread1.join()
thread2.join()

print("Exiting Main Thread")

Kết quả:

Copy
Starting Thread-1
Starting Thread-2
Exiting Thread-1
Exiting Thread-2
Exiting Main Thread

Đồng bộ hóa luồng

Khi làm việc với các luồng, bạn cần đảm bảo rằng các luồng không truy cập đồng thời vào các tài nguyên dùng chung, gây ra các vấn đề như race condition. Python cung cấp các công cụ đồng bộ hóa như Lock, RLock, Semaphore, và Event để giải quyết vấn đề này.

Sử dụng Lock

Lock là một công cụ đồng bộ hóa đơn giản, cho phép một luồng chiếm quyền truy cập vào tài nguyên dùng chung.

Ví dụ:

python Copy
import threading

class Counter:
    def __init__(self):
        self.value = 0
        self.lock = threading.Lock()

    def increment(self):
        with self.lock:
            self.value += 1

counter = Counter()

def worker():
    for _ in range(100000):
        counter.increment()

threads = []
for _ in range(10):
    thread = threading.Thread(target=worker)
    threads.append(thread)
    thread.start()

for thread in threads:
    thread.join()

print(f"Final counter value: {counter.value}")

Kết quả:

Copy
Final counter value: 1000000

Sử dụng RLock

RLock (Reentrant Lock) là một loại khóa cho phép một luồng có thể chiếm quyền truy cập vào tài nguyên nhiều lần mà không bị khóa.

Ví dụ:

python Copy
import threading

class ReentrantCounter:
    def __init__(self):
        self.value = 0
        self.lock = threading.RLock()

    def increment(self):
        with self.lock:
            self.value += 1
            self.double_increment()

    def double_increment(self):
        with self.lock:
            self.value += 1

counter = ReentrantCounter()

def worker():
    for _ in range(100000):
        counter.increment()

threads = []
for _ in range(10):
    thread = threading.Thread(target=worker)
    threads.append(thread)
    thread.start()

for thread in threads:
    thread.join()

print(f"Final counter value: {counter.value}")

Kết quả:

Copy
Final counter value: 2000000

Sử dụng Semaphore

Semaphore là một công cụ đồng bộ hóa cho phép giới hạn số lượng luồng có thể truy cập vào tài nguyên cùng một lúc.

Ví dụ:

python Copy
import threading
import time

semaphore = threading.Semaphore(2)

def worker(name):
    with semaphore:
        print(f"{name} is working")
        time.sleep(2)
        print(f"{name} is done")

threads = []
for i in range(5):
    thread = threading.Thread(target=worker, args=(f"Thread-{i+1}",))
    threads.append(thread)
    thread.start()

for thread in threads:
    thread.join()

print("Exiting Main Thread")

Kết quả:

Copy
Thread-1 is working
Thread-2 is working
Thread-1 is done
Thread-2 is done
Thread-3 is working
Thread-4 is working
Thread-3 is done
Thread-4 is done
Thread-5 is working
Thread-5 is done
Exiting Main Thread

Sử dụng Event

Event là một công cụ đồng bộ hóa cho phép một luồng chờ đợi cho đến khi một sự kiện cụ thể xảy ra.

Ví dụ:

python Copy
import threading
import time

event = threading.Event()

def worker():
    print("Worker is waiting for the event")
    event.wait()
    print("Worker received the event")

thread = threading.Thread(target=worker)
thread.start()

time.sleep(2)
print("Main thread is setting the event")
event.set()

thread.join()
print("Exiting Main Thread")

Kết quả:

Copy
Worker is waiting for the event
Main thread is setting the event
Worker received the event
Exiting Main Thread

Multithreading với concurrent.futures

Python cung cấp module concurrent.futures để đơn giản hóa việc quản lý các luồng và tiến trình. Module này cung cấp lớp ThreadPoolExecutor để quản lý các luồng.

Ví dụ:

python Copy
from concurrent.futures import ThreadPoolExecutor
import time

def worker(name):
    print(f"{name} is working")
    time.sleep(2)
    print(f"{name} is done")

with ThreadPoolExecutor(max_workers=3) as executor:
    futures = [executor.submit(worker, f"Thread-{i+1}") for i in range(5)]

print("Exiting Main Thread")

Kết quả:

Copy
Thread-1 is working
Thread-2 is working
Thread-3 is working
Thread-1 is done
Thread-2 is done
Thread-3 is done
Thread-4 is working
Thread-5 is working
Thread-4 is done
Thread-5 is done
Exiting Main Thread

Multithreading và GIL (Global Interpreter Lock)

Python sử dụng GIL (Global Interpreter Lock) để đảm bảo rằng chỉ có một luồng Python thực thi tại một thời điểm. Điều này có thể hạn chế hiệu suất của các ứng dụng CPU-bound khi sử dụng multithreading. Tuy nhiên, GIL không ảnh hưởng đến các tác vụ I/O-bound, vì vậy multithreading vẫn rất hữu ích trong các tình huống này.

Kết luận

Multithreading là một kỹ thuật mạnh mẽ trong Python, giúp cải thiện hiệu suất và khả năng đáp ứng của ứng dụng. Bằng cách sử dụng module threadingconcurrent.futures, bạn có thể dễ dàng tạo và quản lý các luồng, đồng bộ hóa truy cập vào tài nguyên dùng chung và xử lý các tác vụ đồng thời. Hy vọng rằng bài viết này đã cung cấp cho bạn một cái nhìn tổng quan và chi tiết về multithreading trong Python.

Avatar
Được viết bởi

Admin Team

Gợi ý câu hỏi phỏng vấn

Không có dữ liệu

Không có dữ liệu

Gợi ý bài viết

Không có dữ liệu

Không có dữ liệu

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào