Java同步的静态方法:locking对象或类

Java教程说:“同一对象上的两个同步方法的调用不可能交错。

这对static method意味着什么? 由于静态方法没有关联的对象,所以synchronized关键字会locking类,而不是对象?

由于静态方法没有关联的对象, 所以synchronized关键字会locking类,而不是对象?

是。 🙂

为了给奥斯卡(简单的答案)增加一些细节,Java语言规范的相关部分是8.4.3.6,“同步方法” :

同步方法在执行之前获取监视器(第17.1节)。 对于类(静态)方法,使用与方法类的Class对象关联的监视器。 对于实例方法,使用与此相关联的监视器(为其调用方法的对象)。

有一点你必须小心(几个程序员通常陷入这个陷阱)是,在同步静态方法和同步非静态方法之间没有联系,即:

 class A { static synchronized f() {...} synchronized g() {...} } 

主要:

 A a = new A(); 

主题1:

 Af(); 

主题2:

 ag(); 

f()和g()不是相互同步的,因此可以完全同时执行。

除非你执行g()如下:

 g() { synchronized(getClass()) { ... } } 

当我想在对象的不同实例之间实现互斥(例如访问外部资源时需要)时,我发现这种模式也很有用。

查看关于内部锁和同步的 oracle文档页面

您可能想知道在调用静态同步方法时会发生什么,因为静态方法与类关联,而不是对象。 在这种情况下,线程获取与该类关联的Class对象的内部锁因此,对类的静态字段的访问由与该类的任何实例的锁截然不同的锁来控制

一个静态方法也有一个关联的对象。 它属于JDK工具箱中的Class.class文件。 当.class文件加载到ram中时,Class.class会创build一个名为template object的实例。

例如: – 当你尝试从现有的客户类创build对象

 Customer c = new Customer(); 

Customer.class加载到RAM中。 在那个时候,JDK工具包中的Class.class创build一个名为Template对象的Object,并将该Customer.class加载到该模板对象中。该Customer.class的静态成员变成该模板对象中的属性和方法。

所以一个静态方法或属性也有一个对象

对于那些不熟悉的静态同步方法locking类对象,例如对于string类的String.class,而实例同步方法locking在Java中的“this”关键字所表示的Object的当前实例上。 由于这两个对象是不同的,所以它们有不同的锁,所以当一个线程正在执行静态同步方法时,java中的其他线程不需要等待那个线程返回,而是获得单独的锁,表示字节.class文本,并进入静态同步方法。

下面的例子给出了类和对象锁之间的更清晰,希望下面的例子也会帮助别人:)

例如我们有下面的方法一个获取类和其他获取对象锁:

 public class MultiThread { public static synchronized void staticLock() throws InterruptedException { for (int i = 0; i < 10; i++) { Thread.sleep(100); System.out.println(Thread.currentThread().getName() + " " + i); } } public synchronized void objLock() throws InterruptedException { for (int i = 0; i < 10; i++) { Thread.sleep(100); System.out.println(Thread.currentThread().getName() + " " + i); } } } 

所以,现在我们可以有以下几种情况:

  1. 当使用相同对象的线程尝试同时访问objLock staticLock方法(两个线程都尝试访问相同的方法)

     Thread-0 0 Thread-0 1 Thread-0 2 Thread-0 3 Thread-0 4 Thread-1 0 Thread-1 1 Thread-1 2 Thread-1 3 Thread-1 4 
  2. 当使用相同对象的线程尝试同时访问staticLockobjLock方法(尝试访问不同的方法)

     Thread-0 0 Thread-1 0 Thread-0 1 Thread-1 1 Thread-0 2 Thread-1 2 Thread-1 3 Thread-0 3 Thread-0 4 Thread-1 4 
  3. 当使用不同对象的线程尝试访问staticLock方法时

     Thread-0 0 Thread-0 1 Thread-0 2 Thread-0 3 Thread-0 4 Thread-1 0 Thread-1 1 Thread-1 2 Thread-1 3 Thread-1 4 
  4. 当使用不同对象的线程尝试访问objLock方法时

     Thread-0 0 Thread-1 0 Thread-0 1 Thread-1 1 Thread-0 2 Thread-1 2 Thread-1 3 Thread-0 3 Thread-0 4 Thread-1 4