Java 同步静态变量
我通过同步静态对象(一个变量)所理解的是,如果一个线程正在访问它,另一个线程就不能Java 同步静态变量,java,multithreading,Java,Multithreading,我通过同步静态对象(一个变量)所理解的是,如果一个线程正在访问它,另一个线程就不能 class T3 { static Integer i = 0; static void callStatic() { synchronized(T3.class) { System.out.println(i++); while(true); } }
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();
}
}
但此演示程序的输出为:
调用静态
0
呼叫非静态
一,
我的理解错了吗?还是我遗漏了什么
我尝试了,同步callStatic
方法,并同步T3.class
class对象。但是没有一个像我想的那样有效
注意:我想,1不会被打印,因为callStatic锁定了变量I,并且处于无限循环中。您不同步变量,而是同步对象
callStatic
在1
上同步,然后将i
设置为2
。如果此时notStatic
要输入synchronized(i)
块,它将在2
上同步。没有其他线程已锁定2
,因此它将继续
(实际上,1
和2
不是对象,而是Integer.valueOf(1)
和Integer.valueOf(2)
返回对象,编译器自动插入Integer.valueOf
调用以将int
s转换为Integer
s)
在代码中,
notStatic
实际上根本不同步。确实,对于特定对象,在特定时间只有一个线程可以在同步的块中,但这对不尝试进入同步的块的其他线程没有影响。如果不同步变量,则同步对象
callStatic
在1
上同步,然后将i
设置为2
。如果此时notStatic
要输入synchronized(i)
块,它将在2
上同步。没有其他线程已锁定2
,因此它将继续
(实际上,1
和2
不是对象,而是Integer.valueOf(1)
和Integer.valueOf(2)
返回对象,编译器自动插入Integer.valueOf
调用以将int
s转换为Integer
s)
在代码中,notStatic
实际上根本不同步。确实,对于特定对象,在特定时间只能有一个线程处于同步的块中,但这对不尝试进入同步的块的其他线程没有影响。静态和非静态的同步块不会相互阻塞。您需要了解synchronized
是如何实现这一点的。同步始终在对象上完成,而不是在变量上完成。同步时,线程会锁定对象的监视器,即放入synchronized
语句中的对象
静态引用上的同步块(如在代码中)锁定在类的.class对象上,而不是该类的任何实例上。所以静态和非静态同步块不会相互阻塞
现在,在您的代码中,notStatic
方法不会在任何地方同步,因为callStatic
在静态i
整数对象上同步。所以它们不会互相阻塞。静态和非静态上的同步块不会互相阻塞。您需要了解synchronized
是如何实现这一点的。同步始终在对象上完成,而不是在变量上完成。同步时,线程会锁定对象的监视器,即放入synchronized
语句中的对象
静态引用上的同步块(如在代码中)锁定在类的.class对象上,而不是该类的任何实例上。所以静态和非静态同步块不会相互阻塞
现在,在您的代码中,notStatic
方法不会在任何地方同步,因为callStatic
在静态i
整数对象上同步。因此它们不会互相阻塞。注意:这个答案与原始问题有关,在调用静态中,它是同步的(i)
,而不是同步的(T3.class)
。编辑确实改变了问题
synchronize
作用于对象,而不是持有它的变量/成员。在您的代码中有两件重要的事情
synchronize(i)
确实同步了对i
的访问,前提是尝试使用它的其他代码也同步。它对不同步的代码没有影响。假设线程A同步(i)
并保持它(您的无限循环);然后线程B执行System.out.println(i)代码>线程B可以愉快地阅读i
,没有什么可以阻止它。线程B必须这样做
synchronize (i) {
System.out.println(i);
}
…以便受线程A的同步(i)
的影响。您的代码正在(尝试)同步变异,但无法访问
i++带有整数的code>实际上等同于i=new Integer(i.intValue()+1)
,因为Integer
是不可变的。因此,它创建一个不同的Integer
对象,并将其存储在i
成员中。因此,在旧的Integer
对象上同步的任何内容都不会对新对象上的代码同步产生影响。因此,即使您的代码正在同步访问和变异,也没关系,因为同步将在旧对象上进行
这意味着callStatic
中的代码正在Integer
的一个实例上同步,然后重复创建一组其他实例,但它没有在这些实例上同步
注意:此答案与原始问题相关,原始问题在callStatic
中有已同步(i)
,而不是已同步(T3.class)
。