Java 同步静态方法:锁定对象或类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/437620/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 14:35:49  来源:igfitidea点击:

Java synchronized static methods: lock on object or class

javaclassstaticmethodssynchronized

提问by jbu

The Java documentation says:

Java 文档说:

It is not possible for two invocations of synchronized methods on the same object to interleave.

对同一对象的同步方法的两次调用不可能交错。

What does this mean for a static method? Since a static method has no associated object, will the synchronized keyword lock on the class, instead of the object?

这对静态方法意味着什么?由于静态方法没有关联的对象,synchronized 关键字会锁定类而不是对象吗?

采纳答案by OscarRyz

Since a static method has no associated object, will the synchronized keyword lock on the class, instead of the object?

由于静态方法没有关联的对象, synchronized 关键字会锁定类而不是对象吗?

Yes. :)

是的。:)

回答by Cowan

Just to add a little detail to Oscar's (pleasingly succinct!) answer, the relevant section on the Java Language Specification is 8.4.3.6, 'synchronized Methods':

只是为 Oscar 的(令人愉悦的简洁!)答案添加一些细节,Java 语言规范的相关部分是8.4.3.6,“同步方法”

A synchronized method acquires a monitor (§17.1) before it executes. For a class (static) method, the monitor associated with the Class object for the method's class is used. For an instance method, the monitor associated with this (the object for which the method was invoked) is used.

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

回答by jfpoilpret

One point you have to be careful about (several programmers generally fall in that trap) is that there is no link between synchronized static methods and sync'ed non static methods, ie:

您必须注意的一点(一些程序员通常会陷入该陷阱)是同步静态方法和同步非静态方法之间没有联系,即:

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

Main:

主要的:

A a = new A();

Thread 1:

主题 1:

A.f();

Thread 2:

主题 2:

a.g();

f() and g() are not synchronized with each other and thus can execute totally concurrently.

f() 和 g() 彼此不同步,因此可以完全并发执行。

回答by jfpoilpret

Unless you implement g() as follows:

除非你实现 g() 如下:

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

I find this pattern useful also when I want to implement mutual exclusion between different instances of the object (which is needed when accesing an external resource, for example).

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

回答by Ravindra babu

Have a look at oracle documentation page on Intrinsic Locks and Synchronization

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

You might wonder what happens when a static synchronized method is invoked, since a static method is associated with a class, not an object. In this case, the thread acquires the intrinsic lock for the Class object associated with the class. Thus access to class's static fields is controlled by a lock that's distinct from the lock for any instance of the class.

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

回答by Pahansith Gunathilake

A static method also has an associated object. It belongs to Class.class file in JDK toolkit. When the .class file load into the ram, the Class.class creates a instance of it called template object.

静态方法也有一个关联的对象。它属于 JDK 工具包中的 Class.class 文件。当 .class 文件加载到 ram 中时,Class.class 会创建它的一个实例,称为模板对象。

Eg :- when you try to create object from existing customer class like

例如:- 当您尝试从现有客户类创建对象时

Customer c = new Customer();

The Customer.class load into RAM. In that moment Class.class in JDK toolkit creates an Object called Template object and load that Customer.class into that template object.Static members of that Customer.class become attributes and methods in that template object.

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

So a static method or attribute also has an object

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

回答by Pragya

For those who are not familiar static synchronized method locked on class object e.g. for string class its String.class while instance synchronized method locks on current instance of Object denoted by “this” keyword in Java. Since both of these object are different they have different lock so while one thread is executing static synchronized method , other thread in java doesn't need to wait for that thread to return instead it will acquire separate lock denoted byte .class literal and enter into static synchronized method.

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

回答by Ravi

Below examples gives more clarity between class and object lock, hope below example will help others as well :)

下面的例子更清楚地说明了类和对象锁,希望下面的例子也能帮助其他人:)

For example we have below methods one acquire class and other acquire object lock :

例如,我们有以下方法,一个获取类,另一个获取对象锁:

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

So, now we can have following scenarios :

所以,现在我们可以有以下场景:

  1. When threads using same Objecttries to access objLockORstaticLockmethod same time (i.e. both threads are trying to access same method)

    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. When threads using same Objecttries to access staticLockand objLockmethods same time (tries accessing different methods)

    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. When threads using different Objecttries to access staticLockmethod

    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. When threads using different Objecttries to access objLockmethod

    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
    
  1. 当使用相同对象的线程尝试同时访问objLockORstaticLock方法时(即两个线程都尝试访问相同的方法)

    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