2014-10-18 50 views
2

我知道那個問題「兩個同步方法是否同時執行」之前已經問過,答案是「否。只有一個線程可以保存該對象的鎖,然後它只是那個可以進入同步方法的線程那個對象。「 但是,如果其真正的話,請幫我理解下面的代碼輸出:類有2個同步方法..當一個線程在第二個方法裏面時另一個線程可以進入第一個方法嗎?

public class SynchronizationMistake { 

public int count; 

public synchronized int getCount() 
{ 
    return count; 
} 
public synchronized String incrementCount() 
{ 
    count++; 
    return""; 
} 

public static void main (String args[]) 
{ 
    SynchronizationMistake syn = new SynchronizationMistake(); 
    Thread first = new Thread(syn.new readIncrementCount(syn),"First"); 
    Thread second = new Thread(syn.new readIncrementCount(syn), "Second"); 
    Thread third = new Thread(syn.new readIncrementCount(syn), "Third"); 

    first.start(); 
    second.start(); 
    third.start(); 

} 
private class readIncrementCount implements Runnable 
{ 

    SynchronizationMistake syn; 
    readIncrementCount(SynchronizationMistake syn) 
    { 
     this.syn = syn; 
    } 
    @Override 
    public void run() { 

     System.out.println("I am "+Thread.currentThread().getName()+".Count is "+ syn.getCount()); 
     System.out.println("I am "+Thread.currentThread().getName()+".Incrementing count now"+syn.incrementCount()); 
     System.out.println("I am "+Thread.currentThread().getName()+". After Increment Count is "+ syn.getCount()); 


    } 

} 

}

Output is : 
I am First.Count is 0 
I am First.Incrementing count now 
I am First. After Increment Count is 1 
I am Third.Count is 0 
I am Second.Count is 0 
I am Third.Incrementing count now 
I am Second.Incrementing count now 
I am Third. After Increment Count is 3 
I am Second. After Increment Count is 3 

輸出變化我每次運行這個程序的時間。我懷疑當第二/第三線程得到CPU爲什麼它沒有讀'count'爲1(由第一個線程更新)?換句話說,當第一個線程鎖定'syn'並將count更新爲1時,第二個/第三個線程如何設法進入'getCount'方法。

回答

5

語句System.out.println("I am "+Thread.currentThread().getName()+".Count is "+ syn.getCount());不是以原子方式執行的。部分syn.getCount()可以在println之前執行。這也似乎發生在你的例子中。所有線程首先執行syn.getCount(),那時計數仍爲0,然後才執行其餘的操作。

0

您發佈的這個特定執行會發生什麼情況,即所有三個線程都讀取的計數器值爲零,但是線程一有機會在其他人之前完成其所有輸出,即對計數器的訪問被正確同步,但後來的打印由於輸出緩衝而顯示較舊的值。

嘗試在第一個線程啓動後進行睡眠,這應該不太可能再次發生。

0

正如Henry提到的,所有線程都可以先執行syn.getCount(),然後執行syn.incrementCount。我已經修改了你的代碼稍微改變println語句賦予更好的畫面......

public class SynchronizationMistake { 

public int count; 

public synchronized int getCount() 
{ 
    return count; 
} 

public synchronized String incrementCount() { 

    System.out.println("I am " + Thread.currentThread().getName() + ", incrementing the count from " + count); 
    count++; 
    System.out.println("I am " + Thread.currentThread().getName() + ", incremented the count to " + count); 
    return""; 
} 

public static void main (String args[]) 
{ 
    SynchronizationMistake syn = new SynchronizationMistake(); 
    Thread first = new Thread(syn.new readIncrementCount(syn),"First"); 
    Thread second = new Thread(syn.new readIncrementCount(syn), "Second"); 
    Thread third = new Thread(syn.new readIncrementCount(syn), "Third"); 

    first.start(); 
    second.start(); 
    third.start(); 

} 
private class readIncrementCount implements Runnable 
{ 

    SynchronizationMistake syn; 
    readIncrementCount(SynchronizationMistake syn) 
    { 
     this.syn = syn; 
    } 
    @Override 
    public void run() { 

     System.out.println("Current count is " + syn.getCount()); 
     System.out.println(syn.incrementCount()); 
     System.out.println("Current count is " + syn.getCount()); 
    } 

} 

} 

不同的輸出可以如下......

輸出#1:

Current count is 0 
I am Second, incrementing the count from 0 
Current count is 0 
I am Second, incremented the count to 1 

Current count is 1 
I am First, incrementing the count from 1 
I am First, incremented the count to 2 

Current count is 2 
Current count is 2 
I am Third, incrementing the count from 2 
I am Third, incremented the count to 3 

Current count is 3 

輸出#2:

Current count is 0 
Current count is 0 
Current count is 0 
I am Second, incrementing the count from 0 
I am Second, incremented the count to 1 

I am Third, incrementing the count from 1 
I am Third, incremented the count to 2 

I am First, incrementing the count from 2 
I am First, incremented the count to 3 

Current count is 3 
Current count is 3 
Current count is 3 
相關問題