0

在 Cadence/Temporal 工作流程编程中:

  • 不允许使用本机线程库。例如,在 Java 中,线程必须通过Async.procedureor创建,Async.function而在 Golang 中,线程必须通过workflow.Go. 所以为什么?
  • 有没有像使用本机线程这样的赛车条件?例如Hashtable,还是ConcurrentHashMap应该用来代替HashMap线程安全?
4

1 回答 1

0

概括:

工作流执行必须是确定性的。这是历史回放重建线程状态所必需的。为了具有确定性,Cadence/Temporal 以协作的方式控制线程调度(而不是像大多数操作系统那样抢占式):

  • 任何时间点都只能运行一个工作流线程
  • 只有当当前正在执行的工作流线程被其他东西阻塞时,它才会让步并让下一个工作流线程运行。
  • “下一个工作流线程”的顺序是确定的。

所以:

  • 工作流代码中永远不允许使用本机线程库,因为 Cadence/Temporal 将失去对确定性的控制
  • 由于协作多线程,我们通常遇到的赛车情况永远不会发生。HashMap在工作流代码中使用是安全的。

更多细节

Cadence/Temporal SDK 有一个 DeterministicRunner 来操纵线程执行。例如Java SDKGolang SDK。这个确定性的运行器将决定以正确的顺序运行哪个工作流线程,并且一次运行一个。对于每个决策任务,它将循环执行,直到“所有线程都被阻塞”——RunUntilAllBlocked/ExecuteUntilAllBlocked。

Async.procedure//会创建一个新线程并添加到deterministicRunnerAsync.functionworkflow.Go的列表中,这样执行就会受到控制。

因为任何时候只能执行一个线程,所以我们在常规代码中遇到的大多数竞速情况都不会发生。

但是,这并不意味着根本没有比赛条件。在某些情况下,仍然会有条件导致一些死锁。

换句话说,合作并不意味着没有比赛条件或僵局。这只是意味着死锁情况要少得多。并且没有像抢占式线程调度那样导致脏读的竞争条件。

死锁示例

如果threadA抢到lockA并等待一个activity,那么它让给threadB,然后threadB抢到lockB并等待一个activity;

Activity结束后,threadA会在释放lockA之前尝试获取lockB,threadB会在释放lockA之前尝试获取lockA;

现在,当活动完成时,它们将陷入僵局。

更多参考

https://community.temporal.io/t/how-does-workflow-thread-synchronization-work/504

于 2022-03-04T20:00:08.880 回答