Lean 4(元)编程 Cookbook

并行运行任务🔗

在了解 Task 是什么、以及如何派生和处理它们之前,请先查看 派生任务与工作线程 这篇配方。

并行运行任务🔗

任务最强大的用途之一是同时运行多个 IO 操作。由于 Task α 是异步计算的一个原语,你可以派生多个任务在后台执行 IO,稍后再等待它们的结果。这让你能够交错不同任务的输出,从而展示并发性。

def heavyWork (name : String) (iters : Nat) : IO Unit := do for i in [0:iters] do -- We use a small loop to simulate work let mut _x := 0 for _ in [0:1000] do _x := _x + 1 -- Printing acts as a synchronization/yield point IO.println s!"{name}: step {i}" def runParallel : IO Unit := do IO.println "Starting heavy work..." -- Spawn Task A let taskA IO.asTask (heavyWork "Task A" 5) -- Spawn Task B let taskB IO.asTask (heavyWork "Task B" 2) -- Wait for both to finish let _ IO.wait taskA let _ IO.wait taskB IO.println "Both tasks finished!" /- Task A: step 0 Task B: step 0 Task A: step 1 Task B: step 1 Task A: step 2 Task A: step 3 Task A: step 4 Starting heavy work... Both tasks finished! -/ -- #eval runParallel

在本例中,A 和 B 的输出交错在一起,说明它们在并发运行。注意即便执行了刷新,“Starting heavy work...” 也是稍后才出现。打印输出时并不是直接写到终端,而是写到一个缓冲区,其他工作线程的输出也是如此。因此,受中断频率和线程调度行为影响,主线程与工作线程的输出顺序可能不同 如果你有更好的解释,请分享

然而在许多情况下,由于派生了过多线程,你可能会造成死锁。关于如何区分并避免这类故障,请查看 任务系统中的阻塞与资源耗尽 一节。