簡體   English   中英

如何“解鎖” RwLock?

[英]How to “unlock” an 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顯式調用其析構函數。

這是在兩個地方使用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_lock ,則編譯器將給出錯誤消息,因為在調用drop(read_lock)之后, read_lock沒有保存有效值。 Rust可以使用暫時未初始化的局部變量,但當然,我們需要重新初始化它們,然后才能再次使用它們。

這是編寫線程的主循環以使用范圍替換drop的方式:

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;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM