2013-11-24 52 views
0

我想了解下面java中的線程同步是代碼中有一個名稱爲Interview的主類。在該類我創建兩個對象不能在java中同步方法

public class Interview{ 

    /** 
    * @param args the command line arguments 
    * @throws java.lang.InterruptedException 
    */ 
    public static void main(String[] args) throws InterruptedException { 
     // TODO code application logic here\ 
     Race r1=new Race(); 
     r1.setA(15); 
     Thread t1=new Thread(r1, "First thread"); 
     Race r2=new Race(); 
     r2.setA(25); 

     Thread t2=new Thread(r2, "Second thread"); 
     t1.start(); 
     t2.start(); 
     } 
} 

有具有與名族這裏的run方法其它類的代碼

public class Race implements Runnable{ 
    int a; 

    public int getA() { 
     return a; 
    } 

    public void setA(int a) { 
     this.a = a; 
    } 
    @Override 
    public void run() { 
     try { 

       print(); 



     } catch (InterruptedException ex) { 
      Logger.getLogger(Race.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 
    public synchronized void print() throws InterruptedException{ 
     for(int i=1;i<=10;i++){ 
      System.out.println(a*i); 
      Thread.sleep(1000); 
     } 

    } 
} 

對於每一個對象,我給人一種不同的價值觀和然後嘗試使打印方法同步但不起作用。我正在使用的概念是兩個試圖同時訪問分片資源的線程不能通過使用同步方法來實現。所以在我的情況下,兩個線程t1和t2試圖同時訪問print方法,所以我使用print方法的synchronized關鍵字,但結果仍然是一樣的。我想要的是線程t1首先執行我,例如。 15 30 45 60 .....然後線程t2即25 50 75 ...依此類推。 如果我的概念不清楚,請糾正我。

+0

方法不是共享資源!共享資源只能是類對象的字段。在你的例子中沒有共享資源,因爲兩個Race實例都有自己的字段a。 – isnot2bad

回答

2

您的同步方法是一種實例方法。這意味着通過實例本身獲得了獲取同步的鎖。因此,當你的線程運行時,你將獲得一個超過r1的鎖,另一個超過r2。因此,它工作正常,這不是你所期望的。

看起來你想在r1和r2之間建立互斥。爲此,您的方法需要是靜態的,以便通過類對象獲取鎖。或者您需要使用兩個線程共享的不同鎖對象(僅基於您的示例看起來沒有必要)。

換句話說,你的線程不共享同一個對象,因此它們之間沒有任何競爭條件。

例如,您可以通過使兩個線程使用Race的相同實例或創建由兩者共享的互斥對象來創建互斥。

像這樣:

class Race { 
    public void synchronized print(){ 
    ... 
    } 
} 

Race r = new Race(); 
Thread t1 = new Thread(r); 
Thread t2 = new Thread(r); //notice both threads share r. 

t1.start(); 
t2.start(); 

在上面的例子中,兩個線程將嘗試運行相同的對象上的打印方法。這意味着,synchornized關鍵字在此處創建互斥塊。當時只有一個線程可以獲得對比賽對象的鎖定。

如果您使用Race的兩個不同實例,那麼創建互斥就沒有意義了。由於沒有競態條件,使線程在彼此之間協調沒有意義。那隻會讓他們無需任何延遲。

+0

如果我使該方法爲靜態,那麼我將無法訪問變量bcoz它不是靜態的,除靜態方法外,還可以通過何種方法獲得對類的鎖定。你說關於不同的鎖如何可能 –

+0

@RiteshSangwan讓兩個線程使用同一個'''Race'''對象。或者讓他們共享一些其他的對象,你可以像'''synchronized'(lock){...}''' –

+0

OKk現在我理解了這個概念,但是如果我使用相同的方法,我怎樣才能爲兩個線程單獨設置A種族類的例子。 –

1

該規則實際上是兩個方法,即同步對象不能同時運行。

聲明爲synchronized的非靜態方法在其對象上同步,因此每個Race中的print()方法在它自己的Race對象上同步。

您可以聲明一個同步塊,其中包含在共享對象(如Race.class)上同步的方法的主體。

0

它不能保證哪個線程將首先執行。它由JVM決定哪個線程將首先開始。正如你所說的What I want is thread t1 to execute first i,e. 15 30 45 60..... then thread t2 i.e, 25 50 75... and so on,你可以使用join()方法。它將確保其他線程只有在加入線程完成後纔會執行。欲瞭解更多信息,請參閱this

0
public class Race implements Runnable { 
    private final Object lock; 

    public Race(Object lock) { 
     this.lock = lock; 
    } 

    @Override 
    public void run() { 
     try { 
      print(); 
     } catch (InterruptedException ex) { 
      Logger.getLogger(Race.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 

    public void print() throws InterruptedException { 
     synchronized(lock) { 
      for(int i = 1; i <= 10; i++){ 
       System.out.println(i); 
       Thread.sleep(1000); 
      } 
     } 
    } 
} 

public class Interview{ 
    public static void main(String[] args) throws InterruptedException { 
     Object lock = new Object(); 

     Race r1 = new Race(lock); // <== lock object 
     Thread t1 = new Thread(r1, "First thread"); 

     Race r2 = new Race(lock); // <== same lock object 
     Thread t2 = new Thread(r2, "Second thread"); 

     t1.start(); 
     t2.start(); 
    } 
}