java同步静态变量
我通过同步静态对象(一个变量)所理解的是,如果一个线程正在访问它,另一个线程就不能
class T3
{
static Integer i = 0;
static void callStatic()
{
synchronized(T3.class)
{
System.out.println(i++);
while(true);
}
}
public void notStatic()
{
System.out.println(i++);
while(true);
}
}
class T2 implements Runnable
{
public void run()
{
System.out.println("calling nonstatic");
new T3().notStatic();
}
}
class T implements Runnable
{
public void run()
{
System.out.println("calling static");
T3.callStatic();
}
}
public class Test
{
public static void main(String[] args)
{
new Thread(new T()).start();
try
{
Thread.sleep(100);
}
catch (InterruptedException e)
{
}
new Thread(new T2()).start();
}
}
但是这个演示程序的输出是:
calling static
0
calling nonstatic
1
我的理解错了吗?还是我错过了什么
我尝试了同步callStatic
方法,也同步了T3.class
类对象。但没有一个像我想的那样有效
注意:我想,不会打印1,因为callStatic锁定了变量I,并且处于无限循环中
# 1 楼答案
注意:这个答案与原来的问题有关,这个问题在
callStatic
中有synchronized(i)
,而不是synchronized(T3.class)
。编辑确实改变了问题synchronize
作用于对象,而不是持有它的变量/成员。在你的代码中有几件重要的事情synchronize(i)
确实会同步对i
的访问,前提是其他试图使用它的代码也会同步。它对不同步的代码没有影响。假设线程A执行synchronize(i)
并持有它(你的无限循环);然后线程B做System.out.println(i);
线程B可以愉快地读取i
,没有什么可以阻止它。线程B必须这样做。。。为了受线程A的
synchronize(i)
的影响。您的代码正在(尝试)同步变异,但无法访问带有
Integer
的i++;
实际上等同于i = new Integer(i.intValue() + 1)
,因为Integer
是不可变的。因此,它创建了一个不同的对象Integer
,并将其存储在i
成员中。因此,在旧Integer
对象上同步的任何内容都不会对新对象上的代码同步产生影响。所以,即使你的代码同时同步了访问和变异,这也无关紧要,因为同步将在旧对象上进行这意味着
callStatic
中的代码正在Integer
的一个实例上同步,然后重复创建一组其他实例,但它没有在这些实例上同步# 2 楼答案
静态和非静态上的同步块不会相互阻塞。你需要了解
synchronized
是如何实现这一点的。同步总是在对象上完成,而不是在变量上完成。同步时,线程会锁定对象的监视器,即放在synchronized
语句大括号中的对象静态引用(如代码中)上的同步块锁定在。类的对象,而不是该类的任何实例。所以静态和非静态同步块不会相互阻塞
现在,在您的代码中,
notStatic
方法不会在任何地方同步,因为callStatic
在静态i
整数对象上同步。这样他们就不会互相阻碍# 3 楼答案
不同步变量,而是同步对象
callStatic
在1
上同步,然后将i
设置为2
。如果此时notStatic
要输入synchronized(i)
块,它将在2
上同步。没有其他线程锁定2
,所以它继续(实际上,
1
和2
不是对象,而是Integer.valueOf(1)
和Integer.valueOf(2)
返回对象,编译器会自动插入Integer.valueOf
调用以将int
转换为Integer
在代码中,
notStatic
实际上根本不同步。的确,在特定的时间,对于特定的对象,只有一个线程可以在synchronized
块中,但这对不尝试进入synchronized
块的其他线程没有影响