1

免责声明:此代码是从用于静态和非静态方法的同步块中复制而来的

我对其进行了一些修改。我想知道如何让线程同时调用同步的静态和非静态方法。我可以通过将非静态方法包装在同步块中来使其工作。还有其他方法吗?

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

2 回答 2

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
        }
    }
}

这应该使得这两种方法中只有一种在多个线程中同时运行。

几个提示:

  • 总是synchronized(variable)variable那个final.
  • MUTEX不必是严格的互斥锁,它可以是一个实际的对象。请参见下面的示例。
  • 记住synchronized方法上的修饰符是如何有效实现的。这就像orsynchronized上的一个块。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

于 2012-10-24T23:20:37.733 回答
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);
            } 
        } 
    }
}
于 2012-10-24T22:31:49.877 回答