2014-04-15 36 views
1

我研究ReentrantReadWriteLock在鎖定writeLock時ReentrantReadWriteLock被讀取了嗎?

我寫測試簡單的代碼(我知道,使用Thread.sleep()方法不能保證預測的結果,但我認爲我很幸運:)):

public class RWLock { 
    private static String val = "old"; 
    private static ReadWriteLock lock = new ReentrantReadWriteLock(); 
    private static long time = System.currentTimeMillis(); 
    public void read() { 
     try { 
      lock.readLock().lock(); 
      System.out.println("read " + val +" - "+(System.currentTimeMillis()-time)); 
      Thread.sleep(300); 
     } catch (InterruptedException e) { 

     } finally { 
      lock.readLock().unlock(); 
     } 
    } 

    public void write() { 
     try { 
      lock.writeLock().lock(); 
      val = "new"; 
      System.out.println("write " + val+" - "+(System.currentTimeMillis()-time)); 
      Thread.sleep(10000); 
     } catch (InterruptedException e) { 

     } finally { 
      lock.writeLock().unlock(); 
     } 
    } 
} 

class Tester { 
    public static void main(String[] args) throws InterruptedException { 

     new MyThreadRead().start(); 

     Thread.sleep(400); 
     new MyThreadWrite().start(); 
    } 

} 

class MyThreadRead extends Thread { 
    @Override 
    public void run() { 
     for (int i = 0; i < 10; i++) { 
      new RWLock().read(); 
      try { 
       Thread.sleep(200); 
      } catch (InterruptedException e) { 
      } 
     } 
    } 
} 

class MyThreadWrite extends Thread { 
    @Override 
    public void run() { 
     new RWLock().write(); 
    } 
} 

輸出:

read old - 0 
write new - 401 
read new - 10401 
read new - 10902 
read new - 11402 
read new - 11902 
read new - 12402 
read new - 12902 
read new - 13402 
read new - 13902 
read new - 14402 

10401 - 401 == 10000

10000現在是寫作時間。

正如我所理解的第二個讀線程在寫入之前無法完成。因此寫作和二讀並行執行。對我來說這不是可預測的行爲。

您對此有何看法?

回答

0

也許你有更多的sleep()調用比你意識到的要多。 MyThreadRead#run()和RWLock()#read()中的睡眠調用最多可以添加500 ms。所以這裏發生了什麼。

At T=0, the reader thread grabs the read lock and sleeps for 300ms. 
At T=300, the reader releases the lock, and then sleeps for another 200ms. 
At T=400, the writer grabs the write lock and sleeps for ten seconds, 
At T=500, the reader tries to grab the read lock, but it is blocked by the writer. 
At T=10400, the writer gives up the lock, and then the reader gets to go round 
    its loop nine more times. 

P.S .:移動你的鎖()調用出的try/finally語句的。例如,

...lock() 
try { 
    ... 
} finally { 
    ...unlock(); 
} 

這樣,如果lock()調用引發異常,則不會調用unlock()。

相關問題