Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 如何";解锁";一个锁?_Multithreading_Rust_Mutex - Fatal编程技术网

Multithreading 如何";解锁";一个锁?

Multithreading 如何";解锁";一个锁?,multithreading,rust,mutex,Multithreading,Rust,Mutex,我正在努力解决这个问题。在每个线程中,我读取令牌值 如果它不是我的,检查它是否是节目的结尾 如果是,则完成线程 否则,请再次阅读并重复 如果它是我的(即有我的id),那么获取写锁,增加令牌的值,检查它是否结束,然后告诉主线程我完成了它并完成了当前线程循环 如果没有结束,则释放写锁,然后重新开始读取 没有解锁。这里有我需要的那种解锁吗 似乎我也应该释放读锁,因为如果有人读取数据,写锁就不会发生。有必要吗 fn main() { use std::sync::{Arc, RwLock

我正在努力解决这个问题。在每个线程中,我读取令牌值

  • 如果它不是我的,检查它是否是节目的结尾

    • 如果是,则完成线程
    • 否则,请再次阅读并重复
  • 如果它是我的(即有我的id),那么获取写锁,增加令牌的值,检查它是否结束,然后告诉主线程我完成了它并完成了当前线程循环

  • 如果没有结束,则释放写锁,然后重新开始读取

没有解锁。这里有我需要的那种解锁吗

似乎我也应该释放读锁,因为如果有人读取数据,写锁就不会发生。有必要吗

fn main() {
    use std::sync::{Arc, RwLock};
    use std::thread;
    use std::sync::mpsc::channel;

    const N: usize = 5; //503;
    const STOP_POINT: usize = 100;

    let n = Arc::new(RwLock::new(1));

    let (sender, reciever) = channel();

    for i in 1..N {
        let (n_c, channel) = (n.clone(), sender.clone());
        // println!("Thread n.{} beeing created!", i);

        let a = thread::Builder::new()
            .name(i.to_string())
            .spawn(move || -> () {
                loop {
                    let mut read_only = n_c.read().unwrap();
                    let say_my_name = (*thread::current().name().unwrap()).to_string();

                    // println!("Thread {} says: gonna try!", say_my_name);
                    while (*read_only % N) != i {
                        if *read_only == 0 {
                            break;
                        }
                        // println!("Thread {} says: aint mine!", say_my_name);
                        read_only = n_c.read().unwrap();
                    } // WAIT

                    println!("Thread {} says: my turn!", say_my_name);
                    let mut ref_to_num = n_c.write().unwrap();
                    *ref_to_num += 1;

                    if *ref_to_num == STOP_POINT {
                        channel.send(say_my_name).unwrap();
                        break;
                    }
                }
                ()
            });
        assert_eq!(a.is_ok(), true);
        // thread::spawn();
        // println!("Thread n.{} created!", i);
    }

    println!("{}", reciever.recv().unwrap());
}

要释放锁,可以让它脱离作用域,或者通过调用显式调用其析构函数

下面介绍如何在两个位置使用
drop
编写程序:

fn main() {
    use std::sync::{Arc, RwLock};
    use std::sync::mpsc::channel;
    use std::thread;
    use std::time::Duration;

    const N: usize = 503;
    const STOP_POINT: usize = 100;

    let n = Arc::new(RwLock::new(1));

    let (sender, receiver) = channel();

    for i in 1..N {
        let (n_c, channel) = (n.clone(), sender.clone());
        // println!("Thread n.{} beeing created!", i);

        thread::Builder::new()
            .name(i.to_string())
            .spawn(move || {
                loop {
                    let mut read_only = n_c.read().unwrap();
                    let say_my_name = (*thread::current().name().unwrap()).to_string();

                    // println!("Thread {} says: gonna try!", say_my_name);
                    while (*read_only % N) != i {
                        if *read_only == 0 {
                            break;
                        }

                        drop(read_only); // release the lock before sleeping
                        // println!("Thread {} says: aint mine!", say_my_name);
                        thread::sleep(Duration::from_millis(1));
                        read_only = n_c.read().unwrap();
                    }

                    println!("Thread {} says: my turn!", say_my_name);
                    drop(read_only); // release the read lock before taking a write lock
                    let mut ref_to_num = n_c.write().unwrap();
                    *ref_to_num += 1;

                    if *ref_to_num == STOP_POINT {
                        channel.send(say_my_name).unwrap();
                        break;
                    }
                }
            })
            .expect("failed to spawn a thread");
        // println!("Thread n.{} created!", i);
    }

    println!("{}", receiver.recv().unwrap());
}
请注意,如果我们在
while
循环中不重新分配
read\u lock
,编译器将给出一个错误,因为调用
drop(read\u lock)
read\u lock
没有保存有效值。对于暂时未初始化的局部变量,Rust是可以接受的,但在再次使用它们之前,我们当然需要重新初始化它们

下面是如何编写线程的主循环,以使用作用域替换一个
drop
s:

loop {
    let say_my_name = (*thread::current().name().unwrap()).to_string();
    {
        let mut read_only = n_c.read().unwrap();

        // println!("Thread {} says: gonna try!", say_my_name);
        while (*read_only % N) != i {
            if *read_only == 0 {
                break;
            }

            drop(read_only);
            thread::sleep(Duration::from_millis(1));
            // println!("Thread {} says: aint mine!", say_my_name);
            read_only = n_c.read().unwrap();
        }

        println!("Thread {} says: my turn!", say_my_name);
    } // read_only is dropped here

    let mut ref_to_num = n_c.write().unwrap();
    *ref_to_num += 1;

    if *ref_to_num == STOP_POINT {
        channel.send(say_my_name).unwrap();
        break;
    }
}

谢谢我有点理解,如果一个锁不在作用域内,那么它就会被释放,但我可以想出如何使它发生在写锁上。这滴水正是我需要的。