我试图在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
。怎么会发生这种事?在同步块之外,第二个线程没有修改这个值。还是我的示例代码有问题??
您需要在方法
之外声明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
}
}
这将给你你想要的结果。
原因:
你可以看看这个:为什么局部变量线程安全在Java
字符串myX是一个局部变量,这意味着当每个线程执行testMethod(字符串x)时,它将创建一个对任何其他线程都不可见的唯一副本。
如果您想更改myX,我建议使用全局变量。