rust std::sync::Mutex与时雄::sync::Mutex之间有什么区别?

lqfhib0f  于 2022-12-04  发布在  其他
关注(0)|答案(1)|浏览(180)

什么是“async”互斥锁,而不是“normal”互斥锁?我相信这就是时雄的Mutex和标准的std lib Mutex的区别。但是我不明白,从概念上讲,互斥锁怎么可能是“async”的。关键不就是一次只能有一个东西使用它吗?

mwg9r5ms

mwg9r5ms1#

以下是它们用法的简单比较:

let mtx = std::sync::Mutex::new(0);
let _guard = mtx.lock().unwrap();

let mtx = tokio::sync::Mutex::new(0);
let _guard = mtx.lock().await;

两者都确保互斥性。* 异步 * 互斥体和 * 同步 * 互斥体之间的唯一区别是它们在试图获取锁时的行为。如果同步互斥体试图在锁已经被锁定时获取锁,它将 * 阻止 * 线程上的执行。如果异步互斥体试图在锁已经被锁定时获取锁,它将把执行让给执行器。
如果你的代码是同步的,那么就没有理由使用异步互斥锁。如上所示,锁定异步互斥锁是基于Future的,并且被设计为在async/await上下文中使用。
如果您的代码是异步的,您可能仍然希望使用同步互斥锁,因为这样开销更小。但是,您应该注意,要不惜一切代价避免在async/await上下文中阻塞。因此,只有在获取锁不会阻塞的情况下,您才应该使用同步互斥锁。请记住以下几种情况:

  • 如果你需要在.await调用上持有锁,使用异步互斥锁。当使用线程安全的future时,编译器通常会拒绝这样做,因为大多数同步互斥锁不能被发送到另一个线程。
  • 如果您的锁是有争议的(即,如果您希望互斥锁在您需要时已经被锁定),则应该使用异步互斥锁。当将多个任务同步到池或绑定队列时,可能会发生这种情况。
  • 如果您有复杂的和/或计算量大的更新,那么无论如何都应该将这些更新移动到一个阻塞池中,在那里您将使用同步互斥锁。

上述案例都是同一枚硬币的三个方面:如果您希望阻塞,请使用异步互斥体。**如果您不知道使用互斥体是否会阻塞,请谨慎使用异步互斥体。**在同步互斥体就足够的情况下使用异步互斥体只会给表留下少量性能,而在本应使用异步互斥体的情况下使用同步互斥体可能会带来灾难性后果。
我遇到的大多数情况都是在同步简单的数据结构时使用互斥锁,在这种情况下,update方法被很好地封装起来,以获取锁、更新数据和释放锁。您知道一个简单的println!需要锁定一个互斥锁吗?互斥锁的使用可以是同步的,甚至可以在异步上下文中使用。即使锁阻塞了,它通常并不比始终发生的进程上下文切换更有影响力。

  • 注意:* 时雄的Mutex确实有一个.blocking_lock()方法,如果需要两种锁定行为,这个方法很有帮助。因此互斥体可以是同步的,也可以是异步的!

另请参阅:

相关问题