为什么 Java 同步线程打印顺序不正确?



我正在运行这个java线程示例:

public class Locks1 extends Thread {
private Object lock;
private int myId;
public Locks1( Object l, int id ) { 
lock = l; myId = id; 
}
public void run() { 
synchronized( lock ) {
for ( int i = 0; i < 3; i++ ) {
System.out.println( "Thread #" + myId + " is tired" ); 
try {
Thread.currentThread().sleep( 10 );
} catch ( InterruptedException e ){
} System.out.println("Thread #" + myId + " is rested" );
}
}
}
public static void main( String args[] ) {
Integer lock = new Integer( 0 );
for ( int i = 0; i < 4; i++ ) {
new Locks1( lock, i ).start(); 
}
}
}

我有这个结果:

Thread #0 is tired
Thread #0 is rested
Thread #0 is tired
Thread #0 is rested
Thread #0 is tired
Thread #0 is rested
Thread #3 is tired
Thread #3 is rested
Thread #3 is tired
Thread #3 is rested
Thread #3 is tired
Thread #3 is rested
Thread #2 is tired
Thread #2 is rested
Thread #2 is tired
Thread #2 is rested
Thread #2 is tired
Thread #2 is rested
Thread #1 is tired
Thread #1 is rested
Thread #1 is tired
Thread #1 is rested
Thread #1 is tired
Thread #1 is rested

我不明白为什么它按这个顺序打印。谁能帮我理解为什么序列是 0321 而不是 0123?

谢谢

在你的代码中,第一个问题是锁定资源必须是最终对象,所以像这样声明它:

final Integer lock = new Integer( 0 );

如果没有此语义,不同的线程可能会锁定不同的对象,但对同一对象进行操作。

并解释您观察到的行为。

虽然目标可能是提高整体性能,但与单线程方法相比,使用多线程总是会带来一些性能成本。其中包括与线程之间的协调(锁定、信令、同步(相关的开销、增加的上下文切换、线程创建和拆卸以及调度开销。ref.ch-11.1

如前所述,与单线程程序相比,锁定和上下文切换以及信令与多线程相关联。例如,在您的情况下,您获得序列"0321"的原因不是在另一台机器中可重现的。

Thread.start()方法调用系统本机方法start0,系统分配资源,如果线程锁定任何资源(它确实如此(。由于您的方法需要时间(无论多么小(来完成run()方法,因此其他线程正在等待

一个简单的区别 将您的代码更改为此代码将产生不同的输出。因为这在处理器恢复并在Integer lock上获取下一个锁定的线程的计时和调度方面引入了差异。简而言之,这不是可重现的输出,并且在 1001 尝试"可能是"中会有所不同。

final Integer lock = new Integer( 0 );
for ( int i = 0; i < 4; i++ ) {
System.out.println("starting : " + i);
new Locks1( lock, i ).start();
}

输出:

starting : 0
starting : 1
Thread #0 is tired
Thread #0 is rested
Thread #0 is tired
Thread #0 is rested
Thread #0 is tired
Thread #0 is rested
Thread #1 is tired
Thread #1 is rested
Thread #1 is tired
Thread #1 is rested
Thread #1 is tired
Thread #1 is rested
starting : 2
Thread #2 is tired
Thread #2 is rested
Thread #2 is tired
Thread #2 is rested
Thread #2 is tired
Thread #2 is rested
starting : 3
Thread #3 is tired
Thread #3 is rested
Thread #3 is tired
Thread #3 is rested
Thread #3 is tired
Thread #3 is rested

注意:这在您的机器中可能无法重现。

当多个线程正在等待获取锁并且它最终可用时,无法保证将选择哪个线程。它可以是任何一个。如果多次执行测试,可能会得到不同的结果。

相关内容

  • 没有找到相关文章

最新更新