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

发布于 2024-07-12 05:17:43 字数 261 浏览 9 评论 0原文

Java 文档 说:

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

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

The Java documentation says:

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

拔了角的鹿 2024-07-19 05:17:43

只是为了向 Oscar 的答案添加一些细节(非常简洁!),Java 语言规范的相关部分是 8.4.3.6,'同步方法'

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

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':

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.

放飞的风筝 2024-07-19 05:17:43

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

是的。 :)

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

Yes. :)

青衫负雪 2024-07-19 05:17:43

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

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

Main:

A a = new A();

Thread 1:

A.f();

Thread 2:

a.g();

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

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:

A.f();

Thread 2:

a.g();

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

番薯 2024-07-19 05:17:43

除非您按如下方式实现 g():

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

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

Unless you implement g() as follows:

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).

∞觅青森が 2024-07-19 05:17:43

查看有关 内在锁和同步 的 Oracle 文档页面

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

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

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.

难忘№最初的完美 2024-07-19 05:17:43

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

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

Customer c = new Customer();

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

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

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.

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.

So a static method or attribute also has an object

烟酉 2024-07-19 05:17:43

下面的示例使类锁和对象锁之间的关系更加清晰,希望下面的示例对其他人也有帮助:)

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

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

    <前><代码>线程-0 0
    线程-0 1
    线程0 2
    线程-0 3
    线程-0 4
    线程 1 0
    线程 1 1
    线程 1 2
    线程 1 3
    线程 1 4

  2. 当使用相同对象的线程尝试同时访问staticLockobjLock方法时(尝试访问不同的方法)

    <前><代码>线程-0 0
    线程 1 0
    线程-0 1
    线程 1 1
    线程0 2
    线程 1 2
    线程 1 3
    线程-0 3
    线程-0 4
    线程 1 4

  3. < p>当使用不同对象的线程尝试访问staticLock方法

    <前><代码>线程-0 0
    线程-0 1
    线程0 2
    线程-0 3
    线程-0 4
    线程 1 0
    线程 1 1
    线程 1 2
    线程 1 3
    线程 1 4

  4. 当使用不同对象的线程尝试访问时objLock方法

    <前><代码>线程-0 0
    线程 1 0
    线程-0 1
    线程 1 1
    线程0 2
    线程 1 2
    线程 1 3
    线程-0 3
    线程-0 4
    线程 1 4

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 Object tries to access objLock OR staticLock method 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 Object tries to access staticLock and objLock methods 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 Object tries to access staticLock 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
    
  4. When threads using different Object tries to access objLock method

    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
    
素染倾城色 2024-07-19 05:17:43

对于那些不熟悉锁定在类对象上的静态同步方法的人,例如,对于字符串类,它是String.class,而实例同步方法锁定由“this”关键字表示的对象的当前实例。 Java。

由于这两个对象不同,它们具有不同的锁,因此当一个线程正在执行静态同步方法时,java中的另一个线程不需要等待该线程返回,而是会获取一个单独的锁,表示为byte .class 文字并进入静态同步方法。

来源: https://javarevisited.blogspot.com/ 2012/03/mixing-static-and-non-static.html

For those who are not familiar static synchronized method locked on class object e.g. for string class, it's String.class while instance synchronized method locks on the current instance of Object denoted by “this” keyword in Java.

Since both of these objects are different they have a different lock so while one thread is executing the static synchronized method, the other thread in java doesn’t need to wait for that thread to return instead it will acquire a separate lock denoted byte .class literal and enter into the static synchronized method.

Source: https://javarevisited.blogspot.com/2012/03/mixing-static-and-non-static.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文