简体   繁体   English

为什么 Java 同步线程打印乱序?

[英]Why Java synchronized threads printing out of order?

I am running this java thread example :我正在运行这个 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(); 
        }
    }
}

And I am having this result:我得到了这个结果:

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

I don't understand why it prints in this order.我不明白为什么它按这个顺序打印。 Can anyone please help me to understand why the sequence is 0321 instead of 0123?谁能帮我理解为什么序列是 0321 而不是 0123?

Thanks谢谢

In your code, the first issue is that lock resource has to be a final object so declare it like this :在您的代码中,第一个问题是锁资源必须是最终对象,因此如下声明:

final Integer lock = new Integer( 0 );

As without this semantics, different threads might be locking on the different object however operating on the same object.由于没有这种语义,不同的线程可能会锁定不同的对象,但会在同一对象上运行。

And an explanation to the behaviour you observed.以及对您观察到的行为的解释。

While the goal maybe to improve performance overall, using multiple threads always introduces some performance costs compared to the single threaded approach.虽然目标可能是提高整体性能,但与单线程方法相比,使用多线程总是会带来一些性能成本。 These include the overhead associated with coordinating between threads(locking, signaling, synchronization),increased context switching,thread creation and teardown, and scheduling overhead.这些包括与线程之间的协调(锁定、信令、同步)、增加的上下文切换、线程创建和拆卸以及调度开销相关的开销。 ref.ch-11.1 ref.ch-11.1

As stated, locking and context switching and signalling is associated with multithreading as compared to single threaded programs.如上所述,与单线程程序相比,锁定和上下文切换和信号通知与多线程相关。 In your case, the reason you get the sequence "0321" is not something reproducible in another machine for example.例如,在您的情况下,您获得序列“0321”的原因在另一台机器上无法重现。

The Thread.start() method invokes the system native method start0 and the system allocates resources and if the thread locks any resources (which it does). Thread.start()方法调用系统本地方法start0并且系统分配资源以及线程是否锁定任何资源(它这样做)。 As your method takes time (however small) to complete the run() method the other threads are on wait由于您的方法需要时间(无论多小)来完成run()方法,因此其他线程正在等待

A simple difference changing your code to this will make a different output.将代码更改为此的简单区别将产生不同的输出。 As this introduces differences in the timing and scheduling of which thread the processor resumes and acquires the next lock on Integer lock .因为这引入了处理器恢复和获取下一个Integer lock线程的时序和调度的差异。 In short, this is not a reproducible output and will be different in the 1001 try "may be".简而言之,这不是可重复的输出,并且在 1001 尝试“可能是”中会有所不同。

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

outputs:输出:

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

NOTE: This again might not be reproducible in your machine.注意:这也可能无法在您的机器中重现。

When several threads are waiting to acquire a lock and it finally becomes available, there is no guarantee what thread will be chosen.当多个线程正在等待获取锁并且它最终变得可用时,无法保证将选择哪个线程。 It can be any one.它可以是任何一个。 If you execute the test several times, you might get different results.如果多次执行测试,可能会得到不同的结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM