Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/346.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 同步静态变量_Java_Multithreading - Fatal编程技术网

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)