java - 类的静态方法之间的同步

标签 java multithreading synchronization locking static-methods

我写了下面的代码:

public class ClassAndObjectLock {
 public static void main(String[] args) {
  new Thread(new EvenThread()).start();
  new Thread(new OddThread()).start();
 }
}

class EvenThread implements Runnable {
 public void run() {
  for (int i = 0; i < 10; i += 2) {
   CommonClass.printEvenNumber(i);
  }
 }
}

class OddThread implements Runnable {
 public void run() {
  for (int i = 1; i < 10; i += 2) {
   CommonClass.printOddNumber(i);
  }
 }
}

class CommonClass {
 public static void printEvenNumber(int num) {
  synchronized (CommonClass.class) {
   System.out.println("Even :" + num);
  }
 }

 public static void printOddNumber(int num) {
  synchronized (CommonClass.class) {
   System.out.println("Odd :" + num);
  }
 }
}

当我执行上面的代码时,输​​出如下:

Even :0
Odd :1
Even :2
Odd :3
Even :4
Odd :5
Even :6
Odd :7
Even :8
Odd :9

我不明白这个输出。根据我的理解,当 new Thread(new EvenThread()).start(); 被执行时,它会产生一个类 EvenThread 的线程,它应该获取 的锁code>CommonClass 并保持锁定,直到它打印出所有偶数值。 OddThread 的对象只有在 EvenThread 的对象完成后才有机会。因此在我看来输出应该如下:

Even :0  
Even :2
Even :4
Even :6
Even :8
Odd :1
Odd :3
Odd :5
Odd :7
Odd :9

谁能给我解释一下底层逻辑?

最佳答案

As per my understanding, when new Thread(new EvenThread()).start(); is executed, it spawns a thread of class EvenThread which should acquire the lock of CommonClass and keep the lock with itself until it has printed all the even values.

不,不是这样的:

 public static void printOddNumber(int num) {
   synchronized (CommonClass.class) {
       System.out.println("Odd :" + num);
   }
 }

which(因为该方法在监视器类上是静态的),也可以写成

 public static synchronized void printOddNumber(int num) {
       System.out.println("Odd :" + num);
 }

查看同步块(synchronized block)的作用域:它打印一个数字然后释放锁。

如果您想不间断地打印所有数字,则必须在整个 for 循环期间锁定:

public void run() {
  synchronized(CommonClass.class){
    for (int i = 0; i < 10; i += 2) {
     System.out.println("Even :" + num);
    }
  }
}

关于java - 类的静态方法之间的同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4825012/

相关文章:

java - 如何在 dropwizard 1.0.0 中获取 applicationContextPath

c++ - 在C++中的特定线程上执行函数

java - Java线程转储中的线程顺序是什么?

java - 同步部署在不同服务器上的批处理应用程序,仅由一台服务器处理文件

c - 与信号量原语的进程同步

java stacktrace 显示一个阻塞的线程,但没有关于阻塞它的信息

java - Camel,Amazon SQS - 没有类型转换器可用于将类型 : java. lang.String 转换为所需类型 : com. amazonaws.services.sqs.AmazonSQS

java - Solaris 上 Java/C++ 的高可用性和可扩展平台

: Supertypes and Subtypes seem to be equal?的Java实例如何准确测试类型?

c# - 初始化中的ThreadState异常