有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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,并且处于无限循环中


共 (3) 个答案

  1. # 1 楼答案

    注意:这个答案与原来的问题有关,这个问题在callStatic中有synchronized(i),而不是synchronized(T3.class)。编辑确实改变了问题


    synchronize作用于对象,而不是持有它的变量/成员。在你的代码中有几件重要的事情

    • synchronize(i)确实会同步对i的访问,前提是其他试图使用它的代码也会同步。它对不同步的代码没有影响。假设线程A执行synchronize(i)并持有它(你的无限循环);然后线程B做System.out.println(i);线程B可以愉快地读取i,没有什么可以阻止它。线程B必须这样做

      synchronize (i) {
          System.out.println(i);
      }
      

      。。。为了受线程A的synchronize(i)的影响。您的代码正在(尝试)同步变异,但无法访问

    • 带有Integeri++;实际上等同于i = new Integer(i.intValue() + 1),因为Integer是不可变的。因此,它创建了一个不同的对象Integer,并将其存储在i成员中。因此,在Integer对象上同步的任何内容都不会对对象上的代码同步产生影响。所以,即使你的代码同时同步了访问和变异,这也无关紧要,因为同步将在旧对象上进行

      这意味着callStatic中的代码正在Integer的一个实例上同步,然后重复创建一组其他实例,但它没有在这些实例上同步

  2. # 2 楼答案

    静态和非静态上的同步块不会相互阻塞。你需要了解synchronized是如何实现这一点的。同步总是在对象上完成,而不是在变量上完成。同步时,线程会锁定对象的监视器,即放在synchronized语句大括号中的对象

    静态引用(如代码中)上的同步块锁定在。类的对象,而不是该类的任何实例。所以静态和非静态同步块不会相互阻塞

    现在,在您的代码中,notStatic方法不会在任何地方同步,因为callStatic在静态i整数对象上同步。这样他们就不会互相阻碍

  3. # 3 楼答案

    不同步变量,而是同步对象

    callStatic1上同步,然后将i设置为2。如果此时notStatic要输入synchronized(i)块,它将在2上同步。没有其他线程锁定2,所以它继续

    (实际上,12不是对象,而是Integer.valueOf(1)Integer.valueOf(2)返回对象,编译器会自动插入Integer.valueOf调用以将int转换为Integer

    在代码中,notStatic实际上根本不同步。的确,在特定的时间,对于特定的对象,只有一个线程可以在synchronized块中,但这对不尝试进入synchronized块的其他线程没有影响