java文档说明:在同一对象上对同步方法的两次调用不可能交错。这对于静态方法意味着什么?由于静态方法没有关联的对象,synchronized关键字会锁定类而不是对象吗?
ars1skjm1#
对于那些不熟悉的静态同步方法锁定在类对象上的人,例如,对于string class,它的string.class,而示例同步方法锁定在java中由“this”关键字表示的对象的当前示例上。由于这两个对象都是不同的,它们有不同的锁,因此当一个线程执行静态同步方法时,java中的另一个线程不需要等待该线程返回,而是将获取表示为byte.class literal的单独锁并进入静态同步方法。
muk1a3rh2#
只是为了给奥斯卡的作品增加一点细节(令人愉快的简洁!)答:java语言规范的相关部分是8.4.3.6,“synchronized methods”:同步方法获取监视器(§17.1)执行前。对于类(静态)方法,使用与该方法的类的类对象关联的监视器。对于示例方法,使用与此关联的监视器(为其调用方法的对象)。
roqulrg33#
请看一下有关内部锁和同步的oracle文档页您可能想知道调用静态同步方法时会发生什么,因为静态方法与类而不是对象相关联。在这种情况下,线程获取与类关联的类对象的内在锁。因此,对类的静态字段的访问是由一个锁控制的,该锁不同于类的任何示例的锁。
dgtucam14#
下面的例子让类和对象锁更加清晰,希望下面的例子也能帮助其他人:)例如,我们有以下方法一个获取类,另一个获取对象锁:
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); } } }
所以,现在我们可以有以下场景:当使用相同对象的线程尝试访问 objLock 或 staticLock 方法相同的时间(即两个线程都试图访问相同的方法)
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
当使用相同对象的线程尝试访问 staticLock 以及 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
当使用不同对象的线程尝试访问 staticLock 方法
当使用不同对象的线程尝试访问 objLock 方法
b4qexyjb5#
由于静态方法没有关联的对象,synchronized关键字会锁定类而不是对象吗?是。:)
ikfrs5lh6#
静态方法也有一个关联的对象。它属于jdk工具箱中的class.class文件。当.class文件加载到ram中时,class.class会创建一个名为template object的示例。例如:-当您尝试从现有的customer类创建对象时,例如
Customer c = new Customer();
customer.class加载到ram中。此时,jdk工具箱中的class.class创建了一个名为template object的对象,并将该customer.class加载到该模板对象中。该customer.class的静态成员将成为该模板对象中的属性和方法。所以静态方法或属性也有一个对象
arknldoa7#
除非实现g(),如下所示:
g() { synchronized(getClass()) { ... } }
当我想在对象的不同示例之间实现互斥(例如,在访问外部资源时需要互斥)时,我发现这个模式也很有用。
iyfjxgzm8#
有一点你必须小心(几个程序员通常会落入这个陷阱)那就是同步的静态方法和同步的非静态方法之间没有联系,即:
class A { static synchronized f() {...} synchronized g() {...} }
主要内容:
A a = new A();
线程1:
A.f();
螺纹2:
a.g();
f()和g()不同步,因此可以完全并发执行。
8条答案
按热度按时间ars1skjm1#
对于那些不熟悉的静态同步方法锁定在类对象上的人,例如,对于string class,它的string.class,而示例同步方法锁定在java中由“this”关键字表示的对象的当前示例上。由于这两个对象都是不同的,它们有不同的锁,因此当一个线程执行静态同步方法时,java中的另一个线程不需要等待该线程返回,而是将获取表示为byte.class literal的单独锁并进入静态同步方法。
muk1a3rh2#
只是为了给奥斯卡的作品增加一点细节(令人愉快的简洁!)答:java语言规范的相关部分是8.4.3.6,“synchronized methods”:
同步方法获取监视器(§17.1)执行前。对于类(静态)方法,使用与该方法的类的类对象关联的监视器。对于示例方法,使用与此关联的监视器(为其调用方法的对象)。
roqulrg33#
请看一下有关内部锁和同步的oracle文档页
您可能想知道调用静态同步方法时会发生什么,因为静态方法与类而不是对象相关联。在这种情况下,线程获取与类关联的类对象的内在锁。因此,对类的静态字段的访问是由一个锁控制的,该锁不同于类的任何示例的锁。
dgtucam14#
下面的例子让类和对象锁更加清晰,希望下面的例子也能帮助其他人:)
例如,我们有以下方法一个获取类,另一个获取对象锁:
所以,现在我们可以有以下场景:
当使用相同对象的线程尝试访问
objLock
或staticLock
方法相同的时间(即两个线程都试图访问相同的方法)当使用相同对象的线程尝试访问
staticLock
以及objLock
方法相同(尝试访问不同的方法)当使用不同对象的线程尝试访问
staticLock
方法当使用不同对象的线程尝试访问
objLock
方法b4qexyjb5#
由于静态方法没有关联的对象,synchronized关键字会锁定类而不是对象吗?
是。:)
ikfrs5lh6#
静态方法也有一个关联的对象。它属于jdk工具箱中的class.class文件。当.class文件加载到ram中时,class.class会创建一个名为template object的示例。
例如:-当您尝试从现有的customer类创建对象时,例如
customer.class加载到ram中。此时,jdk工具箱中的class.class创建了一个名为template object的对象,并将该customer.class加载到该模板对象中。该customer.class的静态成员将成为该模板对象中的属性和方法。
所以静态方法或属性也有一个对象
arknldoa7#
除非实现g(),如下所示:
当我想在对象的不同示例之间实现互斥(例如,在访问外部资源时需要互斥)时,我发现这个模式也很有用。
iyfjxgzm8#
有一点你必须小心(几个程序员通常会落入这个陷阱)那就是同步的静态方法和同步的非静态方法之间没有联系,即:
主要内容:
线程1:
螺纹2:
f()和g()不同步,因此可以完全并发执行。