繁体   English   中英

线程中的 RwLock::spawn 不会释放锁

[英]RwLock in a thread::spawn doesn't release the lock

我不知道为什么它挂在my.rw.write(); .

如果您取消对sleep呼叫的注释,则它可以正常工作。 这意味着在执行 spawn 线程并释放RwLock之后,写访问尝试仍在阻塞主线程。 我觉得理论上应该没问题。 我哪里错了?

use std::sync::Arc;
use std::sync::RwLock;
use std::{thread, time};

struct MySt {
    num1: i64,
    num2: i64,
    rw: RwLock<Vec<i64>>,
}

fn main() {
    let my = Arc::new(MySt {
        num1: 32,
        num2: 64,
        rw: RwLock::new(vec![1, 2, 3]),
    });
    let my2 = my.clone();
    let t = thread::spawn(move || {
        let mut rw = my2.rw.write().unwrap();
        rw[0] = 5;
        println!("child thread {}, {}, {}, {}", my2.num1, my2.num2, rw[0], rw[1]);
    });
    //thread::sleep(time::Duration::from_millis(1000));
    let mut rw = my.rw.write().unwrap();
    rw[1] = 6;
    println!("main thread {}, {}, {}, {}", my.num1, my.num2, rw[0], rw[1]);
    t.join().unwrap();
}

执行 spawn 线程并释放RwLock后,写访问尝试仍在阻塞主线程

这是不正确的。 添加基本​​调试输出以区分它们表明唯一运行的printlnmain那个。

无法保证在产生子线程后哪个线程将首先执行。 但是,主线程可能会继续运行,因为它已经在运行。 如果是这样,它将通过rw锁定RwLock并保持锁定直到函数结束 但是在函数结束之前,主线程会阻塞等待子线程的加入。 子线程无法完成,因为它必须先获取写锁。 你创造了一个经典的僵局。

要解决此问题,请使用drop或添加范围显式解锁锁以限制锁的生命周期:

fn main() {
    let my = Arc::new(MySt {
        num1: 32,
        num2: 64,
        rw: RwLock::new(vec![1, 2, 3]),
    });
    let my2 = my.clone();
    let t = thread::spawn(move || {
        let mut rw = my2.rw.write().unwrap();
        rw[0] = 5;
        println!("thread a {}, {}, {}, {}", my2.num1, my2.num2, rw[0], rw[1]);
    });
    //thread::sleep(time::Duration::from_millis(1000));
    let mut rw = my.rw.write().unwrap();
    rw[1] = 6;
    println!("thread b {}, {}, {}, {}", my.num1, my.num2, rw[0], rw[1]);
    drop(rw);
    t.join().unwrap();
}

添加sleep很可能会导致子线程先执行。 然后它将获取锁并退出,允许主线程继续。

也可以看看:

它不能正常工作的原因是当主线程中的锁在子线程中的锁之前执行时,我没有释放锁。 我像下面一样修复它。

use std::sync::Arc;
use std::sync::RwLock;
use std::{thread, time};

struct MySt {
    num1: i64,
    num2: i64,
    rw: RwLock<Vec<i64>>,
}

fn main() {
    let my = Arc::new(MySt {
        num1: 32,
        num2: 64,
        rw: RwLock::new(vec![1, 2, 3]),
    });
    let my2 = my.clone();
    let t = thread::spawn(move || {
        let mut rw = my2.rw.write().unwrap();
        rw[0] = 5;
        println!("child thread {}, {}, {}, {}", my2.num1, my2.num2, rw[0], rw[1]);
    });
    {
        let mut rw = my.rw.write().unwrap();
        rw[1] = 6;
        println!("main thread {}, {}, {}, {}", my.num1, my.num2, rw[0], rw[1]);
    }
    t.join().unwrap();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM