2012-10-24 55 views
1

免責聲明:此代碼是從synchronized blocks for static and non-static methods線程調用靜態和非靜態方法

複製我做了一些修改它。我想知道如何使線程調用同步的靜態和非靜態方法。我可以通過將非靜態方法封裝在同步的塊中來使其工作。有沒有其他方法?

public class StaticNonStaticSynch 
{ 
public static void main(String[] args) 
{ 
     final StaticNonStaticTest staticNonStaticTest = new StaticNonStaticTest(); 
    Runnable runnable1 = new Runnable() 
    { 
    @Override 
    public void run() 
    { 
staticNonStaticTest.nonStaticMethod(); 
    } 
    }; 

    Runnable runnable2 = new Runnable() 
    { 
    @Override 
    public void run() 
    { 
    StaticNonStaticTest.staticMethod(); 
    } 
    }; 

    Thread thread1 = new Thread(runnable1, "First Thread"); 
    Thread thread2 = new Thread(runnable2, "Second Thread"); 

    thread1.start(); 
    thread2.start(); 
} 
} 

class StaticNonStaticTest 
{ 

void nonStaticMethod() 
{ 
//synchronized (StaticNonStaticTest.class){ 
    for(int i=0;i<50;i++) 
    { 
    System.out.println("Non - Static method called by " + Thread.currentThread().getName() +" : = "+i); 
    } 
// } 
} 
static synchronized void staticMethod() 
{ 
    for(int i=0;i<50;i++) 
    { 
    System.out.println("Static method called by " + Thread.currentThread().getName() +" : = "+i); 
    } 
} 
} 

回答

4

記住這一點:

public class MyClass { 

    public synchronized void doSomething() { 
     // Do something 
    } 

    public synchronized static void doSomethingStatic() { 
     // Do something static 
    } 
} 

本質編譯成這樣:

public class MyClass { 

    public void doSomething() { 
     synchronized(this) { 
      // Do something 
     } 
    } 

    public static void doSomethingStatic() { 
     synchronized(MyClass.class) { 
      // Do something static 
     } 
    } 
} 

請注意,它們不會在同一事物上同步。爲了解決這個問題,創造對他們倆的目標是鎖定(被稱爲互斥對象,或「互斥」):

public class MyClass { 

    private static final Object MUTEX = new Object(); 

    public void doSomething() { 
     synchronized(MUTEX) { 
      // Do something 
     } 
    } 

    public static void doSomethingStatic() { 
     synchronized(MUTEX) { 
      // Do something static 
     } 
    } 
} 

這應該讓這個只有這兩種方法中的一個正在運行同時跨越多個線程。

一對夫婦提示:

  • variablefinal始終使用synchronized(variable)
  • MUTEX不一定是嚴格的互斥量,它可能是一個實際的對象。看下面的例子。
  • 請記住方法的​​修飾符是如何有效實現的。它就像thisMyClass.class上的​​區塊。

除了有一個對象,是嚴格意義上的互斥體,你可以使用這final任何領域。例如,要迭代期間在Map同步:

public class MyClass { 

    private static final Map<String, String> map = new HashMap<String, String>(); // Java 6 
    private static final Map<String, String> map = new HashMap<>(); // Java 7 

    public static void put(String k, String v) { 
     synchronized(map) { 
      map.put(k, v); 
     } 
    } 

    public static void printAll() { 
     synchronized(map) { 
      for (Entry<String, String> entry : map.entrySet()) { 
       System.out.println(entry.getKey() + ":" + entry.getValue()); 
      } 
     } 
    } 
} 

此代碼可以保證,你永遠不會得到一個ConcurrentModificationException

+0

謝謝布賴恩!!!!!! – user547453

+0

@brian:如果我們鎖定MyClass的實例會怎麼樣?它是否仍然保證我們不會得到ConcurrentModificationException,因爲當前線程在printAll()中時,沒有其他線程能夠訪問put()中的同步塊,並且該映射是私有的? – Kode

+0

@Kode是的,它將保證非併發訪問,但是在該類上同步的任何其他內容也會導致該部分代碼被阻止。儘可能縮小同步範圍以避免瓶頸。 – Brian

2

您可以讓這兩種方法在一個公用鎖對象上進行內部同步。否則,在靜態方法執行時讓實例方法阻塞的唯一方法是在類對象上進行同步(就像在註釋行中一樣)。

同步實例方法在對象實例上同步;同步的靜態方法在類實例上同步。請注意,如果存在兩個類的實例(例如,來自不同的類加載器),那麼同步的靜態方法可能會同時執行。你通常會知道這是否發生,因爲你必須做相當多的工作才能實現。

這裏有一個方法來同步一個共同的鎖定對象靜態和實例方法:

class StaticNonStaticTest { 
    private static final Object LOCK_OBJECT = new Object(); 

    void nonStaticMethod() { 
     synchronized (LOCK_OBJECT) { 
      for (int i=0; i<50; i++) { 
       System.out.println("Non - Static method called by " 
        + Thread.currentThread().getName() + " : = " + i); 
      } 
     } 
    } 

    static void staticMethod() { 
     synchronized (LOCK_OBJECT) { 
      for (int i=0; i<50; i++) { 
       System.out.println("Static method called by " 
        + Thread.currentThread().getName() +" : = "+i); 
      } 
     } 
    } 
} 
+0

我怎樣才能「有兩種方法內部一個共同的鎖定對象的同步操作」? – user547453

+1

@ user547453 - 我更新了我的回答,以顯示我的意思 –

+0

謝謝泰德!!!!!!! – user547453