我正在 OCaml 中使用 Jane Street 的 Async 库进行并发项目。我想让多个 TCP 服务器接受输入,其处理程序操作单个哈希表 (a Hashtbl.t
)。似乎这种情况需要我使用互斥锁 ( Mutex.t
's)来保护我的哈希表。
但是,当我阅读 Async 文档和Real World Ocaml 中有关 Async 的章节时,我的印象是有一个使用Deferred.t
's 和Pipe.t
's的“异步世界” ,以及一个使用线程和互斥体的“系统线程世界”,混合它们的唯一方法是使用Thread_safe
模块,所以我不太习惯将互斥体扔到我的异步计算中。
所以基本上,在异步进行并发计算时,我应该如何保护共享的可变数据结构?
一般来说,如果可以原子地执行某些操作,则不需要使用互斥锁来保护它。但是这句话根据上下文有不同的含义。
在 async 的上下文中,原子操作最严格的定义是这种没有 type 的操作'a Deferred.t
。换句话说,如果它没有被延迟,那么它是原子的,并且在它的执行过程中它不能被任何其他线程中断。实际上,由于async
库实现了协作线程,因此您总是知道给定的函数是否可以被中断,这与抢占线程不同。
这意味着,您可以使用任何 OCaml 模块,当然包括哈希表,而无需任何互斥锁,因为它们的所有操作都是原子的。
协作多线程很少需要互斥锁。通常,实现事务行为。