我正在运行这个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
注意:这在您的机器中可能无法重现。
当多个线程正在等待获取锁并且它最终可用时,无法保证将选择哪个线程。它可以是任何一个。如果多次执行测试,可能会得到不同的结果。