Lập trình không đồng bộ trong Python

Mar 06 2023
Lập trình không đồng bộ là một mô hình lập trình cho phép nhiều quy trình thực hiện đồng thời và độc lập mà không cần đợi một quy trình kết thúc trước khi tiếp tục quy trình tiếp theo. Trong bài đăng trên blog này, chúng ta sẽ xem xét lập trình không đồng bộ là gì và cách sử dụng nó trong python.
Lập trình không đồng bộ trong Python

Lập trình không đồng bộ là một mô hình lập trình cho phép nhiều quy trình thực hiện đồng thời và độc lập mà không cần đợi một quy trình kết thúc trước khi tiếp tục quy trình tiếp theo. Trong bài đăng trên blog này, chúng ta sẽ xem xét lập trình không đồng bộ là gì và cách sử dụng nó trong python.

Lập trình không đồng bộ là gì?

Trong lập trình đồng bộ, máy tính thực hiện các hướng dẫn theo thứ tự tuần tự, chặn thực thi cho đến khi hoàn thành một công việc trước khi chuyển sang công việc tiếp theo.
Mặt khác, lập trình không đồng bộ cho phép chương trình bắt đầu một hoạt động và sau đó chuyển sang hoạt động khác mà không dừng thực thi cho đến khi hoàn thành tác vụ ban đầu.

Lập trình không đồng bộ đặc biệt có lợi trong các trường hợp mà các quy trình, chẳng hạn như hoạt động của I/O mạng hoặc cơ sở dữ liệu, có thể mất nhiều thời gian để hoàn thành. Lập trình không đồng bộ có thể giúp tăng hiệu suất và khả năng đáp ứng trong các ứng dụng phần mềm bằng cách cho phép chương trình tiếp tục các hoạt động khác trong khi chờ một hoạt động chậm hoàn thành.

Tùy thuộc vào ngôn ngữ lập trình và khuôn khổ được sử dụng, lập trình không đồng bộ có thể được thực hiện bằng nhiều chiến lược khác nhau như gọi lại, lời hứa hoặc từ khóa không đồng bộ/chờ đợi.

Sự khác biệt giữa Lập trình không đồng bộ và Mutliprocessing

Sự khác biệt chính giữa lập trình không đồng bộ và đa xử lý là lập trình không đồng bộ cho phép các hoạt động không chặn xảy ra trong một luồng, trong khi đa xử lý sử dụng nhiều lõi hoặc quy trình để hoàn thành công việc đồng thời.

Sự khác biệt giữa lập trình không đồng bộ và phân luồng

Sự khác biệt chính giữa lập trình không đồng bộ và luồng là lập trình không đồng bộ cho phép các hoạt động không chặn bằng cách sử dụng một luồng đơn lẻ, trong khi luồng sử dụng nhiều luồng để thực hiện nhiều tác vụ song song.

Để biết thêm thông tin về sự khác biệt: Chạy bộ so với Lập trình đa xử lý so với Lập trình không đồng bộ

Làm thế nào để sử dụng Asyncio?

Trước tiên, hãy tạo một chương trình đơn giản bắt đầu thực hiện một công việc tại một thời điểm và hoàn thành chúng.

import time
import asyncio

def do_job(s):
    print(f"{s} started")
    await asyncio.sleep(1)
    print(f"{s} done")

def main():
    start = time.perf_counter()
    todo = ["Job A", "Job B", "Job C"]
    for job in todo:
        do_job(job)
    
    end = time.perf_counter()
    print(f"Took: {end-start:.3f} seconds")

main()

# OUTPUT
# Job A started
# Job Adone
# Job B started
# Job B done
# Job C started
# Job C done
# Took: 3.009 seconds

Tạo và chạy các Coroutine

Coroutine là một loại chức năng có thể bị gián đoạn và tiếp tục vào những thời điểm khác nhau trong suốt quá trình thực thi. Nói cách khác, một coroutine cho phép bạn viết mã có thể bị gián đoạn, làm việc khác và sau đó tiếp tục từ nơi dừng lại.

Để tạo coroutines, chúng ta cần sử dụng asynctừ khóa trước deftừ khóa. Gọi một coroutine không gọi chức năng mà chúng tôi muốn chạy. Nó tạo ra một nhiệm vụ.

import time
import asyncio

async def do_job(s):
  ...

async def main():
  ...

main()

asyncio.run(main())

nếu bạn chạy mã này, bạn có thể gặp lỗi như thế này:

RuntimeWarning: coroutine '...' was never awaited

import time
import asyncio

async def do_job(s):
    print(f"{s} started")
    await asyncio.sleep(1)
    print(f"{s} done")

async def main():
    start = time.perf_counter()
    todo = ["Job A", "Job B", "Job C"]
    for job in todo:
        await do_job(job)
    
    end = time.perf_counter()
    print(f"Took: {end-start:.3f} seconds")

asyncio.run(main())

# OUTPUT
# Job A started
# Job A done
# Job B started
# Job B done
# Job C started
# Job C done
# Took: 3.009 seconds

await asyncio.sleep(1)

tasks = [asyncio.create_task(do_job(item)) for item in todo]
done, pending = await asyncio.wait(tasks)

import time
import asyncio

async def do_job(s):
    print(f"{s} started")
    await asyncio.sleep(1)
    print(f"{s} done")

async def main():
    start = time.perf_counter()
    todo = ["Job A", "Job B", "Job C"]
    
    tasks = [asyncio.create_task(do_job(item)) for item in todo]
    done, pending = await asyncio.wait(tasks)
    
    end = time.perf_counter()
    print(f"Took: {end-start:.3f} seconds")

asyncio.run(main())

# OUTPUT
# Job A started
# Job B started
# Job C started
# Job A done
# Job B done
# Job C done
# Took: 1.009 seconds

Bạn có thể xem video để biết thêm thông tin về lập trình bất đồng bộ trong python. ( Giới thiệu về async Python | Viết trình thu thập dữ liệu web )