Java 在线程中同步代码块的Anamoly

Java 在线程中同步代码块的Anamoly,java,multithreading,synchronized,Java,Multithreading,Synchronized,我是java新手,在java线程中实现同步代码块时遇到问题 class btstep extends Thread { private static final Object lock = new Object(); public void run() { synchronized(lock) { System.out.println("3 "); System.out.println("4

我是java新手,在java线程中实现同步代码块时遇到问题

class btstep extends Thread
{
    private static final Object lock = new Object();
    public void run()
    {
        synchronized(lock)
        {
            System.out.println("3 ");
            System.out.println("4 ");
        }
    }
}

class btevent extends Thread
{
    private static final Object locko = new Object();
    public void run()
    {
        synchronized(locko)
        {
            System.out.println("1 ");
            System.out.println("2 ");
        }
    }
}

public class Interleaving
{
    public static btevent bt = new btevent();
    public static btstep bs = new btstep();

    public static void main(String[] args)
    {
        bt.start();
        bs.start();
    }
}
此程序的运行输出为

1
3
2
4
这不是我想要的。同步的代码块在其交织时不再是串行的 我想要的输出是

1
2
3
4


我在程序中做错了什么???

您使用了两个不同的锁对象(
lock
locko
),因此块不是相互排斥的。您需要两个块在同一个锁对象上同步以实现所需的功能。

您使用的是两个不同的锁对象(
lock
locko
),因此这些块不是互斥的。您需要在同一个锁对象上同步两个块以实现所需的功能。

两个线程需要共享同一个锁对象实例,只有这样您才能实现所需的输出。

两个线程需要共享同一个锁对象实例,只有这样,您才能实现所需的输出。

同步时,对象的选择非常重要。如果希望两个线程交互,则它们必须在同一对象上同步

最简单的解决办法是使用

synchronized(System.out) {

同步输出。

同步时,对象的选择非常重要。如果希望两个线程交互,则它们必须在同一对象上同步

最简单的解决办法是使用

synchronized(System.out) {

要同步输出。

要同步2个(或更多)代码块,它们必须在同一对象上同步。在您的情况下,对象是不同的。

要同步2个(或更多)代码块,它们必须在同一对象上同步。在您的情况下,对象是不同的。

您真的建议锁定全局(任何其他组件都可以选择同步不相关的内容)和可变字段吗?我不会那样做。它表明了同步输出的意图。我会按照OP的建议去做,因为使用一个线程会简单得多。您是对的,锁定可变对象和全局对象是个坏主意,但在本例中,这是最简单的解决方案。(除了完全不使用线程之外)您真的建议锁定全局(任何其他组件都可以选择同步不相关的内容)和可变字段吗?我不会那样做。它表明了同步输出的意图。我会按照OP的建议去做,因为使用一个线程会简单得多。您是对的,锁定可变对象和全局对象是个坏主意,但在本例中,这是最简单的解决方案。(除了完全不使用线程之外)您需要将对象与要同步的对象(在本例中为输出流)相关联,并让每个访问该对象的线程通过该对象的同步方法进行同步。(或者显式锁定该对象。)顺便说一句,我不明白为什么锁可以直接“附加”到任何对象,而不是开发人员提出显式的“锁定”同步对象。是否有我看不到的巨大优势?我所看到的是混乱和错误,就像这一个。我猜,在每个Java对象中,保存可能的锁对象的指针现在都是开销?谁在一天早上醒来后大喊“尤里卡——我们会让任何物体都可以锁定!”@MartinJames:AFAIK,每个物体中都没有额外的指针来保持锁定。内在锁是允许同步块和方法(没有传递任何显式锁)存在和工作的东西。@MartinJames:大多数时候,有一个对象表示要锁定的对象。因此,它使普通情况变得更简单。但是,我同意这一点,它会让人们认为锁定并不是他们真正需要认真考虑的事情,因为“它已经在那里了”和“它只需要我在那里输入关键字就可以工作”,这可能会导致类似这样的错误。你需要将一个对象与你想要同步的对象相关联(在本例中为输出流)并让每个访问该对象的线程通过该对象的同步方法执行(或显式锁定该对象)顺便说一句,我不明白为什么锁可以直接“附加”到任何对象,而不是开发人员提出一个显式的“锁”同步对象。是否有一些我看不到的巨大好处?我所看到的只是混乱和错误,就像这一个。我想,现在每个Java对象中都有一个指针来保存一个可能的锁对象?谁一天早上醒来,大喊“尤里卡-我们将使任何对象都可锁定!”@MartinJames:AFAIK,每个对象中都没有额外的指针来持有锁。内在锁是允许同步块和方法(没有任何显式锁传递)的东西存在和工作。@MartinJames:大多数时候,有一个对象代表你想要锁定的东西。因此,它使普通情况变得更简单。然而,我同意,它可以让人们认为锁定并不是一件他们真的需要想得太多的事,因为“它已经在那里了”并且“它只是工作,我不必做任何事情,但把一个关键字在那里”,这可能会导致像这样的错误之一。