Answers:
由于静态方法没有关联的对象, 所以synced关键字会锁定在类而不是对象上吗?
是。:)
this
是在实例方法上获得的锁-请修复此问题。
只是为Oscar的回答(很简洁!)添加了一些细节,Java语言规范中的相关部分是8.4.3.6,“同步方法”:
同步方法在执行之前会获取一个监视器(第17.1节)。对于类(静态)方法,使用与该方法的类的Class对象关联的监视器。对于实例方法,将使用与此实例关联的监视器(为其调用方法的对象)。
您必须要注意的一点(几个程序员通常会陷入该陷阱)是同步的静态方法与同步的非静态方法之间没有链接,即:
class A {
static synchronized f() {...}
synchronized g() {...}
}
主要:
A a = new A();
线程1:
A.f();
线程2:
a.g();
f()和g()彼此不同步,因此可以完全同时执行。
synchronized (MyClass.class) {...}
。
静态方法也具有关联的对象。它属于JDK工具包中的Class.class文件。当.class文件加载到ram中时,Class.class创建它的一个实例,称为模板对象。
例如:-当您尝试从现有客户类别创建对象时,例如
Customer c = new Customer();
将Customer.class加载到RAM中。在那一刻,JDK工具箱中的Class.class创建了一个名为Template对象的对象,并将该Customer.class加载到该模板对象中。该Customer.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);
}
}
}
因此,现在我们可以有以下几种情况:
当使用相同对象的线程尝试同时访问objLock
OR 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
当使用不同Object的线程尝试访问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
当使用不同Object的线程尝试访问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