2017-12-21 29 views
0

私はthread-ring問題を解決しようとしています。それは、スレッドを終了している場合、それはプログラム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()); 
    } 
    
  • 答えて

    3

    ロックを解除するには、あなたはそれがスコープ外に落ちるか、明示的にdropを呼び出すことによって、そのデストラクタを呼び出してみましょう。我々はwhileループ内read_lockを再割り当てしない場合read_lockが成立しないので、コンパイラはエラーを与えること

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

    注:ここでは

    は、プログラムが2つの場所でdropを使って書くことができる方法です有効な値はdrop(read_lock)です。錆は一時的に初期化されていないローカル変数で問題ありませんが、再利用する前に再初期化する必要があります。

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

    ありがとう:ここ

    は、スレッドのメインループはdrop秒のいずれかを置き換えるためにスコープを使用するように書くことができる方法です! ロックが範囲外になった場合、ロックが解除された場合、ロックが解除された場合、ロックを解除する方法を理解することができます。 ドロップは私が必要なものです。 –

    関連する問題