2012-03-04 78 views
2

對於Java而言,我非常失望,因爲它不允許以下代碼以併發方式移動。當沒有同步時,兩個線程更頻繁地切換,但是當嘗試訪問同步方法時,在第二個線程獲得鎖之前,它將花費太長時間(如30秒),並且在第一個線程獲得鎖之前從第二個。什麼編碼可以照顧更好地共享鎖:java中的線程/同步

public synchronized static void i() 
    { 

    System.out.println(Thread.currentThread().getName()); 

    } 
    public static void main(String[] f) 
    { 

    Thread t = new Thread(new Runnable(){ 
    public void run() 
    { 
     while(true) 
     i(); 
    }}); 
    t.setName("a: "); 
    Thread t2 = new Thread(new Runnable(){ 
    public void run() 
    { 
     while(true) 
     i(); 
     }}); 
     t2.setName("b: "); 
     t.start(); 
     t2.start(); 

    } 

回答

7

使用ReentrantLock將公平設置爲true。

public static final ReentrantLock lock = new ReentrantLock(true); 
public static void i() 
{ 
    lock.lock(); 
    try { 
     System.out.println(Thread.currentThread().getName()); 

    } finally { 
     lock.unlock(); 
    } 
} 
+2

結合exabrial和Chikei的答案,你有正確的答案。出於執行原因指出的原因,公平不能被保證。但是在交錯方面,我會和琪琪的建議一起使用一個鎖定,以保證一定的公平性。如果你想'完美'交錯,即線程B總是在線程A之後,線程A再次運行之前運行,那麼你需要一個不同的鎖定方案。 – brettw 2012-03-04 05:44:47

+0

非常感謝,這兩種方法似乎工作得很好 – 2012-03-04 05:54:00

3

問題不是java,它是你的代碼。鎖合同的哪一部分意味着公平收購?簡單地讓一個現有的鎖持有人繼續是更快和更高效的;通常他們會完成工作並釋放鎖。你的程序應該對鎖和線程交織的公平性做出0的假設。

如果你想要一個公平的交錯,你不應該使用同步的方法。您需要創建一個私有對象,然後在該私有對象上手動使用wait()和notify()方法來強制交錯,但即便如此,這也是一個假設:)爲了確保您獲得公平交錯,您必須創建一個volatile條件變量指示誰來執行它。

+0

優秀的這項工作完美 – 2012-03-04 05:51:20