有 Java 编程相关的问题?

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

java这个同步块中发生了什么

我试图查看变量值是否可以在synchronized块之前由多个线程修改。我对下面代码的行为感到困惑。我创建了一个具有synchronized块的方法,如下所示

public void testMethod( String x )
{
    String myX = x.toUpperCase();
    System.out.println( myX ); // Prints the value before the critical section
    synchronized( this )
    {
        try
        {
            Thread.sleep( 5000 );
        }
        catch( InterruptedException e )
        {
            e.printStackTrace();
        }
        System.out.println( myX ); // Prints the value inside the critical section
    }
}

然后,我创建了两个线程,用两个不同的字符串值调用这个方法,如下所示

Thread myThreadOne = new Thread( () -> testMethod( "T1" ) );
Thread myThreadTwo = new Thread( () -> testMethod( "T2" ) );

并在主方法中调用

public static void main( String[] args )
{
    Test t1 = new Test();
    t1.myThreadOne.start();
    t1.myThreadTwo.start();
}

现在我期望的输出是T1T2T2T2T2。或者,无论哪个线程最后启动,都应该在synchronized块之前和内部打印该值,因为很明显,变量myX将在第一个线程处于睡眠状态或第一个线程处于临界段内时具有来自第二个线程的更新值

但是输出总是第一个线程值,然后是第二个线程值。像T1T2T1T2。这是怎么发生的?VaribalemyXsynchronized块之外,不是第二个线程修改此值。还是我的示例代码有问题


共 (2) 个答案

  1. # 1 楼答案

    您需要在method之外声明myx变量:

    String myX;
    
        public void testMethod( String x )
        {
            myX = x.toUpperCase();
            System.out.println( myX ); // Prints the value before the critical section
            synchronized( this )
            {
                try
                {
                    Thread.sleep( 5000 );
                }
                catch( InterruptedException e )
                {
                    e.printStackTrace();
                }
                System.out.println( myX ); // Prints the value inside the critical section
            }
        }
    
    

    这将给你你想要的结果

    原因:

    • 局部变量本质上是线程安全的,不被线程共享
    • 而类变量是共享的

    你可以看看这个:Why are local variables thread safe in Java

  2. # 2 楼答案

    字符串myX是一个局部变量,这意味着当每个线程执行testMethod(字符串x)时,它将创建一个对任何其他线程都不可见的唯一副本

    如果你想改变myX,我建议你使用一个全局变量