gpt4 book ai didi

multithreading - 为什么 Rust 互斥锁似乎没有给最后想要锁定它的线程锁?

转载 作者:行者123 更新时间:2023-11-29 07:45:03 25 4
gpt4 key购买 nike

我想编写一个程序,生成两个锁定 Mutex 的线程,增加它,打印一些东西,然后解锁 Mutex,以便另一个线程可以执行相同的。我添加了一些 sleep 时间以使其更加一致,所以我认为输出应该是这样的:

ping pong ping pong …  

但实际输出是相当随机的。大多数时候,它只是

ping ping ping … pong 

但是根本没有一致性;有时中间也有一个“乒乓球”。

我相信互斥锁有某种方法可以确定谁最后想锁定它,但事实并非如此。

  1. 锁定实际上是如何工作的?
  2. 如何获得所需的输出?
use std::sync::{Arc, Mutex};
use std::{thread, time};

fn main() {
let data1 = Arc::new(Mutex::new(1));
let data2 = data1.clone();
let ten_millis = time::Duration::from_millis(10);

let a = thread::spawn(move || loop {
let mut data = data1.lock().unwrap();
thread::sleep(ten_millis);
println!("ping ");
*data += 1;
if *data > 10 {
break;
}
});

let b = thread::spawn(move || loop {
let mut data = data2.lock().unwrap();
thread::sleep(ten_millis);
println!("pong ");
*data += 1;
if *data > 10 {
break;
}
});

a.join().unwrap();
b.join().unwrap();
}

最佳答案

MutexRwLock 都遵循特定于操作系统的原语,并且不能保证公平。在 Windows 上,它们都是用 SRW locks 实现的这被特别记录为公平。我没有研究其他操作系统,但您绝对不能依赖 std::sync::Mutex 的公平性,尤其是当您需要此代码可移植时。

Rust 中一个可能的解决方案是 Mutex parking_lot crate 提供的实现,它提供了一个 unlock_fair method ,这是用一个公平的算法实现的。

来自parking_lot documentation :

By default, mutexes are unfair and allow the current thread to re-lock the mutex before another has the chance to acquire the lock, even if that thread has been blocked on the mutex for a long time. This is the default because it allows much higher throughput as it avoids forcing a context switch on every mutex unlock. This can result in one thread acquiring a mutex many more times than other threads.

However in some cases it can be beneficial to ensure fairness by forcing the lock to pass on to a waiting thread if there is one. This is done by using this method instead of dropping the MutexGuard normally.

虽然 parking_lot::Mutex 在没有专门使用 unlock_fair 方法的情况下并不声称是公平的,但我发现您的代码产生的 ping 数量与 pong 数量相同,只需进行该切换 ( playground ),甚至不使用 unlock_fair 方法。

通常,当守卫超出范围时,互斥量会自动解锁。为了让它公平解锁,你需要在守卫被放下之前插入这个方法调用:

let b = thread::spawn(move || loop {
let mut data = data1.lock();
thread::sleep(ten_millis);
println!("pong ");
*data += 1;
if *data > 10 {
break;
}
MutexGuard::unlock_fair(data);
});

关于multithreading - 为什么 Rust 互斥锁似乎没有给最后想要锁定它的线程锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56924866/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com