
Trong Python, Thread (luồng) là một kỹ thuật giúp chương trình thực thi nhiều tác vụ cùng lúc, tối ưu hóa thời gian xử lý. Điều này đặc biệt hữu ích khi thực hiện các tác vụ như tải xuống nhiều file, xử lý dữ liệu lớn hoặc tương tác với API mà không làm chậm chương trình chính.
1. Giới thiệu về Thread trong Python
Python hỗ trợ đa luồng thông qua module threading
. Khi sử dụng thread, chương trình có thể chạy nhiều tác vụ đồng thời mà không cần chờ từng tác vụ hoàn thành trước.
Tại sao nên dùng Thread?
✅ Cải thiện hiệu suất: Chạy nhiều tác vụ song song thay vì tuần tự.
✅ Tăng tốc độ xử lý: Hữu ích khi xử lý tác vụ I/O như đọc file, gửi HTTP request.
✅ Giữ giao diện mượt mà: Khi lập trình GUI, sử dụng Thread giúp giao diện không bị đơ.
2. Cách tạo và chạy Thread
Python cung cấp 2 cách tạo thread:
- Dùng
threading.Thread
với hàm có sẵn - Dùng
threading.Thread
với class kế thừa từThread
Cách 1: Sử dụng threading.Thread
với hàm
import threading
import time
def say_hello(name):
for i in range(5):
print(f"Hello, {name}! - {i}")
time.sleep(1)
# Tạo và khởi chạy luồng
thread1 = threading.Thread(target=say_hello, args=("Alice",))
thread2 = threading.Thread(target=say_hello, args=("Bob",))
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print("Tất cả thread đã hoàn thành!")
📌 Giải thích:
threading.Thread(target=say_hello, args=("Alice",))
: Tạo thread mới chạy hàmsay_hello
với tham số"Alice"
..start()
: Bắt đầu thực thi luồng..join()
: Đợi thread hoàn thành trước khi tiếp tục chương trình chính.
Cách 2: Kế thừa Thread
để tạo luồng
import threading
import time
class MyThread(threading.Thread):
def __init__(self, name):
threading.Thread.__init__(self)
self.name = name
def run(self):
for i in range(5):
print(f"{self.name} đang chạy - {i}")
time.sleep(1)
# Tạo và chạy nhiều thread
thread1 = MyThread("Luồng 1")
thread2 = MyThread("Luồng 2")
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print("Hoàn thành tất cả các luồng!")
📌 Giải thích:
- Kế thừa
threading.Thread
và override phương thứcrun()
. - Mỗi thread sẽ chạy phương thức
run()
khistart()
được gọi. - Dùng
.join()
để đảm bảo tất cả thread kết thúc trước khi tiếp tục chương trình.
3. Sử dụng Lock để tránh xung đột dữ liệu
Khi nhiều thread cùng truy cập và chỉnh sửa một tài nguyên chung, có thể xảy ra race condition (xung đột dữ liệu). Để tránh điều này, sử dụng Lock.
import threading
counter = 0
lock = threading.Lock()
def increment():
global counter
for _ in range(100000):
with lock:
counter += 1
thread1 = threading.Thread(target=increment)
thread2 = threading.Thread(target=increment)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print(f"Counter cuối cùng: {counter}")
📌 Giải thích:
lock = threading.Lock()
: Tạo khóa (Lock).with lock:
: Đảm bảo chỉ có một thread truy cậpcounter
tại một thời điểm.- Nếu không có Lock,
counter
có thể không đạt giá trị mong đợi do race condition.
4. Khi nào nên sử dụng Thread?
✅ Khi xử lý các tác vụ I/O-bound như:
- Gửi request HTTP/API.
- Đọc/ghi file hoặc database.
- Tải nhiều hình ảnh cùng lúc.
❌ Không nên dùng Thread khi xử lý CPU-bound (tác vụ nặng như xử lý ảnh, AI).
🔹 Thay vào đó, hãy sử dụng multiprocessing
để tận dụng nhiều CPU core.