首页 > 解决方案 > 这个同步块中发生了什么

问题描述

我试图查看变量值是否可以在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" ) );

并在 main 方法中调用。

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

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

但输出始终是第一个线程值,然后是第二个线程值。像T1, T2, T1, T2. 这是怎么发生的?变量myXsynchronized块外,不是第二个线程修改这个值。还是我的示例代码有问题?

标签: javamultithreading

解决方案


您需要在以下范围内声明myx变量method

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


推荐阅读