2017-04-02 139 views
0

我現在正在學習Java併發。我碰到一段代碼來這樣的:爲什麼我的同步方法鎖定不同的對象?

package pac1; 

import java.util.*; 
import java.util.concurrent.*; 

class A1 { 
    public void f() { 
     synchronized (this) { 
      for (int i = 0; i < 5; i++) 
       System.out.println("f()"); 
     } 
    } 
} 

class B1 { 
    public void g() { 
     synchronized (this) { 
      for (int i = 0; i < 5; i++) 
       System.out.println("g()"); 
     } 
    } 
} 

class C1 { 
    public void p() { 
     synchronized (this) { 
      for (int i = 0; i < 5; i++) 
       System.out.println("p()"); 
     } 
    } 

} 

public class V { 
    public static void main(String[] args) { 
     A1 a = new A1(); 
     B1 b = new B1(); 
     C1 c = new C1(); 
     new Thread() { 
      public void run() { 
       a.f(); 
      } 
     }.start(); 
     new Thread() { 
      public void run() { 
       c.p(); 
      } 
     }.start(); 
     b.g(); 
    } 

} 

由於該代碼使用不同的對象調用同步方法,我認爲它不會妨礙他們互相干擾。但是,結果如下:

​​

BTW,結果是一樣的使用鎖:

package pac1; 

import java.util.*; 
import java.util.concurrent.*; 
import java.util.concurrent.locks.Lock; 
import java.util.concurrent.locks.ReentrantLock; 

class A { 
    Lock lock = new ReentrantLock(); 

    public void f() { 
     lock.lock(); 
     try { 
      for (int i = 0; i < 5; i++) 
       System.out.println("f()"); 
     } finally { 
      lock.unlock(); 
     } 
    } 
} 

class B { 
    Lock lock = new ReentrantLock(); 

    public void g() { 
     lock.lock(); 
     try { 
      for (int i = 0; i < 5; i++) 
       System.out.println("g()"); 
     } finally { 
      lock.unlock(); 
     } 
    } 
} 

class C { 
    Lock lock = new ReentrantLock(); 

    public void p() { 
     lock.lock(); 
     try { 
      for (int i = 0; i < 5; i++) 
       System.out.println("p()"); 
     } finally { 
      lock.unlock(); 
     } 
    } 
} 

public class Ex16 { 

    public static void main(String[] args) { 
     A a = new A(); 
     B b = new B(); 
     C c = new C(); 
     new Thread() { 
      public void run() { 
       a.f(); 
      } 
     }.start(); 
     new Thread() { 
      public void run() { 
       c.p(); 
      } 
     }.start(); 
     b.g(); 
    } 

} 
+0

嘗試打印更多的東西。我猜想Java在創建第二個線程的時候會運行第一個線程的方法,然後在真正開始運行主要方法之前,所以你可以按照1,3,2的順序打印它們。我敢打賭,如果你做了1000人,他們會混在一起。 – gandaliter

+0

是什麼讓你覺得他們互相干擾?在每次迭代時向Thread.sleep(500)添加一個調用。 –

回答

0

其實環路根本沒有足夠長的時間,因此允許線程在同一順序完成他們已啓動。爲了說明線程不會干擾,您可以嘗試以下方法之一:

  • 使循環運行更長時間,例如, 1000次迭代應該更多的則不夠:

    synchronized (this) { for (int i = 0; i < 1000; i++) System.out.println("f()"); }

  • 暫停環路內的線程,但一定要爲每個循環設置不同的時間間隔:

    synchronized (this) { for (int i = 0; i < 5; i++) { System.out.println("p()"); try { Thread.sleep(3000); } catch (final InterruptedException ex) { // Swallow } } }

這麼久故事短小:這些鎖實際上不會干涉。

1

您不需要鎖定或在此同步。 Sychronized用於鎖定對共享可變狀態的訪問。你沒有任何共享的可變狀態開始。

這裏有3個線程,沒有人可以預測這些線程由於上下文切換而運行的順序。我沒有看到問題。

相關問題