根據我的閱讀和理解,每個對象都有在嘗試訪問同步方法時發生的鎖定。這是我的代碼(在 2 個不同的類文件中):public class test { public synchronized void inc1( String who ) { for( int i = 0 ; i < 1500 ; i++ ) System.out.println( who+": "+i ); }}public class testsyn implements Runnable { test k = new test( ); public static void main( String[ ] args ) { new Thread( new testsyn( ) ).start( ); new testsyn( ).doStuff( ); } public void doStuff( ) { k.inc1( "Main" ); } public void run( ) { k.inc1( "Thread" ); }}所以假設我的輸出的第一行是:“Main:0”。這意味著主線程已經獲取了名為“k”的測試對象的密鑰,對吧?我創建的另一個線程怎么可能在主線程完成之前進入“inc1”方法并打印輸出?我注意到這個問題發生在這個特定的模式中,但是如果我將'k'設為靜態并改為寫這個(在testyn類中):public class testsyn implements Runnable { static test k = new test( ); public static void main( String[ ] args ) { new Thread( new testsyn( ) ).start( ); k.inc1( "Main" ); } public void run( ) { k.inc1( "Thread" ); }}這將按我預期的方式工作,并且輸出之間不會發生沖突。例如,如果主線程首先進入同步方法,那么其他線程將不得不等到主線程完成該方法。我在這里要問的問題是這種變化如何影響程序的行為?為什么?
2 回答

江戶川亂折騰
TA貢獻1851條經驗 獲得超5個贊
所以假設我的輸出的第一行是:“Main:0”。這意味著主線程已經獲取了名為“k”的測試對象的密鑰,對吧?我創建的另一個線程怎么可能在主線程完成之前進入“inc1”方法并打印輸出?
你寫“名為'k'的測試對象”就好像只有一個一樣。在您的示例中,k
是 class 的實例變量testsyn
,因此每個實例都有自己的。它們指的是不同的對象,每個對象都有自己的監視器。因此,執行其中一個對象的同步實例方法的線程不會阻止另一個線程執行另一個對象的同步實例方法。
如果我將'k'設為靜態[...],輸出之間就不會發生沖突。
是的。 static
變量屬于聲明它們的類。它們由所有實例共享。兩個線程共享一個 static k
,在運行之前已經初始化main()
并且之后沒有被修改。由于他們都試圖運行同一個對象的同步方法,因此必須等到另一個完成。

慕的地10843
TA貢獻1785條經驗 獲得超8個贊
是的,synchronized
關鍵字是用來獲取鎖的;鎖與對象實例相關聯。你有兩個test
類的實例;一個給每個線程。所以沒有爭議。當字段k
為靜態時,線程之間共享一個實例。
添加回答
舉報
0/150
提交
取消