🦍

Mutexは if let ... else ブロックに渡って保持される話

2023/10/27に公開1

Mutexif let ... elseブロックに渡って保持される話

Twitterで次の記事が流れてきて、所見でなにも分からなかったので調べてみました。

https://qiita.com/t13801206/items/18e4bd372ee258e26d1a

記事のおさらい

上記の記事を読めば分かると思いますが、一応簡潔に説明します。

2つのスレッドからcounterにアクセスする際にロックを取得するが、if let { ... } else { ... }を抜けるまで、別スレッドで取得したロックが開放されない

if let Some(_) = counter.lock().unwrap().checked_div(i) { // lock scope +
                                                          //            |
} else {                                                  //            |
    thread::sleep(time::Duration::from_millis(100));      //            |
}                                                         // -----------+            

しかし、通常のif { ... } else { ... }だと、想定とおりifブロックを抜けた時点でロックが開放される挙動をしている

if counter.lock().unwrap().checked_div(i).is_some() { // lock scope +
                                                      //            |
} else {                                              // -----------+
    thread::sleep(time::Duration::from_millis(100));
}

というお話です。

if let ... elsematchのシンタックスシュガー

if let構文は、matchのシンタックスシュガーと考えることができます。[1]
そのため、デシュガーすると次のようになります。

if let Some(_) = counter.lock().unwrap().checked_div(i) {
} else {
    thread::sleep(time::Duration::from_millis(100));
}

// デシュガー後
let counter = counter.lock().unwrap().checked_div(i);     // lock scope +
match counter {                                           //            |
    Some(_) => {}                                         //            |
    None => {                                             //            |
        thread::sleep(time::Duration::from_millis(100));  //            |
    }                                                     //            |
};                                                        // -----------+

このようにデシュガーするとわかりますが、ロックはmatch式が終わるまで保持します。

また、Clippy先生の方でも「The Mutex lock remains held for the whole if let ... else block and deadlocks.」と書いてあります。

https://rust-lang.github.io/rust-clippy/master/index.html#/if_let_mutex

最後

Rustむずい

参考文献

脚注
  1. https://doc.rust-lang.org/book/ch06-03-if-let.html ↩︎

Discussion

t13801206t13801206

拙文を読んでいただきありがとうございました。

Rust難しいですね

でも、Rustでネットワークプログラミングするのは楽しいです!