如果静态同步方法和实例同步方法尝试在不同线程中访问同一类的静态字段,以下程序的行为会是什么?任何线程都会被阻塞吗?非常混乱。
class MyClass
{
public static int i = 5;
public synchronized void m1()
{
System.out.println(i); //uses static field i of MyClass
//T1 is executing this method
}
public static synchronized void m3()
{
//T2 will be able to call this method on same object lock while it is using
//static field i???
System.out.println(i);//uses static field i of MyClass
}
}
同步实例方法相当于
public void m1() {
synchronized(this) {
...
}
}
(嗯,它们并不完全相同,但你问题的答案不会受到这种差异的影响)。
同步静态方法在类上同步:
public void m2() {
synchronized(MyClass.class) {
...
}
}
如您所见,两个块在不同的对象上同步:
m1
在调用它的实例上同步,而m2
在代表JVM中的类的Class<MyClass>
实例上同步。所以这两个方法可以被调用而不会互相阻塞。
您始终在一个对象上同步。
函数 m1 在调用它的对象的实例上进行同步。
函数 m3 在类本身上同步。
m1 可以写成:
public void m1()
{
synchronized(this) {
System.out.println(i); //uses static field i of MyClass
//T1 is executing this method
}
}
因此,您正在同步两个不同的对象,并且这两个方法可以同时访问任何全局变量。
您的示例代码看起来不错。
根据我的说法,确保静态变量同步的最佳方法是。由于锁对象在您的类之外无法访问。见下文。
public class MyClass
{
private static int i = 0;
private static final Object lockObject = new Object();
public void m1() {
synchronized (lockObject ) {
//Use you static var
}
}
public void m3() {
synchronized (lockObject ) {
//Use you static var
}
}
}
方法m1和m3可以独立执行。
因为正如你已经说过的,
static synchronized
在物体上。因此与synchronize(MyClass.class)
相同。
synchronized
可以在实例范围内使用。因此,它仅针对实例被阻止。这与使用相同:
MyClass myClass = new MyClass();
synchronize (myClass)
{
.....
}
Java 没有任何与访问静态字段相关的同步控制。
如果将方法设为空,同步将完全相同。
具体来说,只要任何线程正在执行该类型中的任何同步静态方法,所有其他调用同步静态方法的线程都会等待它们完成,因此一次最多执行一个同步静态方法。