2013-05-03 107 views
1

在java中,我有2個線程在我的客戶端,一個是控制網絡流量,另一個是處理消息,繪製遊戲等。我試圖做的是當數據包到達時,網絡線程將調用messageReceived遊戲線程的方法,包含消息作爲參數。如果我將函數messageReceived設置爲synchronized,並且在messageReceived函數結束之前有兩個數據包序列地出現,或者它不會阻止,並且數據包丟失,因爲網絡線程無法調用已經在使用的messageReceived函數,它會阻止網絡線程嗎?通過遊戲線程?同步阻塞?

+2

'synchronized'將會阻塞,直到資源被其他線程釋放。 – 2013-05-03 17:47:11

+0

謝謝,所以將messageReceived同步而不會丟包的危險是安全的。 – deniz 2013-05-03 17:48:56

+0

是的,但保持同步塊的簡短。只要有時間按順序接受和處理所有數據包,就不會有問題,因此在獲取數據包之前,沒有OS緩衝區會填滿並丟失數據包。 – 2013-05-03 17:50:33

回答

1

當您使用synchronized關鍵字來同步代碼段時,當另一個線程進入想要訪問該段時,它將阻塞,直到它可以訪問。

0

正確,你在IO線程上阻塞。你只想在messageReceived()上做一些簡單的工作,因爲這可能只是在某種FIFO中排隊消息,以便處理線程稍後處理。你的同步塊應該儘可能小。

0

如果線程在類中調用同步方法,則所有其他線程將被阻塞,以調用該類中的任何同步方法,因爲對象鎖不可用。如果你的messageReceived不在任何共享資源上工作,那麼保持它不同步。如果它使用某個共享資源,則嘗試通過將該代碼包裝在同步塊中來最小化同步代碼。

0

是,​​如果隱式鎖已被另一個線程鎖定,則會阻塞線程。但有一個無阻塞的選擇 - java.util.concurrent.locks.Lock這是更靈活

Lock.tryLock() 
  • 獲取鎖,只有當它是免費的,在調用時

Lock.tryLock(long time, TimeUnit unit) 
  • 如果在給定的等待時間內空閒並且當前線程尚未中斷編輯。
0

它很容易概念化,但更多的是一個視覺的人。這裏有一些代碼幫助我很久以前瞭解了興奮的syncorized以及它的工作原理。如果您觀察輸出,您將在將同步屬性添加到打印功能時看到輸出,而您從不會看到As和Bs混合在一起。但是當你刪除它時,你會看到一個非常不同的輸出。一旦你看到它,它應該是直截了當的。

public class Main { 
    public static void main(String[] args) { 
     (new ThreadA()).start(); 
     (new ThreadB()).start(); 
    } 

    // try it with removing the synchronized: public static void print(String str) { 
    public static synchronized void print(String str) { 
     for(int i = 0; i<100; i++) 
      System.out.print(str); 
     System.out.println(); 
    } 

    public static class ThreadA extends Thread { 
     public void run() { 
      while(true) { 
       print("A"); 
      } 
     } 
    } 
    public static class ThreadB extends Thread { 
     public void run() { 
      while(true) { 
       print("B"); 
      } 
     } 
    } 
}