Java 如何区分已锁定到不同实例的线程?

Java 如何区分已锁定到不同实例的线程?,java,multithreading,thread-synchronization,Java,Multithreading,Thread Synchronization,我了解到线程可以锁定“资源”,比如说他们正在使用的对象,这样一次只允许一个线程使用和修改它,这就是同步问题。我创建了一个类的两个不同实例,并将其提供给我的线程,试图确保它们锁定在不同的“资源”上。他们是如何表现得好像锁定了相同的资源?我很困惑,因为我没有任何关于线程的经验和知识 这是我从在线教程中修改的代码,以尝试我所想的: public class TestThread { public static void main(String args[]) {

我了解到线程可以锁定“资源”,比如说他们正在使用的对象,这样一次只允许一个线程使用和修改它,这就是同步问题。我创建了一个类的两个不同实例,并将其提供给我的线程,试图确保它们锁定在不同的“资源”上。他们是如何表现得好像锁定了相同的资源?我很困惑,因为我没有任何关于线程的经验和知识

这是我从在线教程中修改的代码,以尝试我所想的:

    public class TestThread {
        public static void main(String args[]) {
        PrintDemo PD1 = new PrintDemo("No.1"); //just prints from 1 to 5
        PrintDemo PD2 = new PrintDemo("No.2");

        ThreadDemo T1 = new ThreadDemo( "Thread - 1 ", PD1 );
        ThreadDemo T2 = new ThreadDemo( "Thread - 2 ", PD2 );

        T1.start();
        T2.start();
        // wait for threads to end
        try {
            T1.join();
            T2.join();
        } catch ( Exception e) {
            System.out.println("Interrupted");
        }
    }
}

class ThreadDemo extends Thread {
    private Thread t;
    private String threadName;
    PrintDemo  PD;

    ThreadDemo( String name,  PrintDemo pd) {
        threadName = name;
        PD = pd;
    }

    public void run() {
        synchronized(PD) {
            PD.printCount();
        }
        System.out.println("Thread " +  threadName + " exiting.");
    }

    public void start () {
        System.out.println("Starting " +  threadName );
        if (t == null) {
            t = new Thread (this, threadName);
            t.start ();
        }
    }
}

class PrintDemo {
    private String name;
    PrintDemo(String name) {
        this.name = name;
    }
    public void printCount() {
        try {
            for(int i = 5; i > 0; i--) {
            System.out.println(name + " Counter   ---   "  + i );
            }
        } catch (Exception e) {
        System.out.println("Thread  interrupted.");
        }
    }
}
每次跑步都应该有所不同,但总是一样的:

输出:

Starting Thread - 1 Starting Thread - 2 No.1 Counter --- 5 No.1 Counter --- 4 No.1 Counter --- 3 No.1 Counter --- 2 No.1 Counter --- 1 Thread Thread - 1 exiting. No.2 Counter --- 5 No.2 Counter --- 4 No.2 Counter --- 3 No.2 Counter --- 2 No.2 Counter --- 1 Thread Thread - 2 exiting. 起始线程-1 起始线程-2 1号柜台——5号 1号柜台--4号 1号柜台--3号 1号柜台--2号 1号柜台--1号 线程-1正在退出。 2号柜台——5号 2号柜台--4号 2号柜台--3号 2号柜台--2号 2号柜台--1号 线程-2退出。 编辑#1:我按照你的要求填写了整个代码。我还测试了代码,没有覆盖start。结果是一样的。

如果添加

线程。睡眠(1000)

在PrintDemo的每个刻度之间,您可能会看到两个线程都执行5、4、3等操作。现在第一个线程速度太快,它完成的速度比主线程启动第二个线程的速度快


同步在这里没有效果,两个线程在不同的资源上同步,这没有效果。在证明(使用Thread.sleep)两个线程同时执行之后,然后在共享对象上添加同步,即使等待,两个线程也会一个接一个地完全执行。

问题在于
ThreadDemo.start()
方法

您的
ThreadDemo
类是用
extends-Thread
声明的,但您从未将其实际用作线程。相反,真正的线程对象是在
ThreadDemo.start()中创建的

以下是可能发生的情况:

  • 主线程调用T1.start()
  • 。它创建一个新线程,这需要一些时间,然后启动线程

  • 新线程开始打印它的五行,而主线程同时调用
    T2.start()

  • 调用
    T2.start()
    会创建另一个新线程,这需要一些时间。与此同时,另一条线仍在打印。它不会打印太多的行,而且
    system.out
    是缓冲的,所以很有可能,它能够在任何实际I/O发生之前打印所有行。同时

  • …主线程仍在创建
    T2
    线程。这需要一些时间

  • 最后,主线程能够启动
    T2
    线程,该线程打印其五行,然后


  • …故事结束了。这就是它可能下降的原因。

    您多久运行一次代码?两次输出相同是完全可能的,2000次仍然是可能的,但可能性更大。也许不要打印5次,而是打印1000次,以便给线程更多的发散时间。为什么要重写
    start()
    方法?躲在那里的是什么?重写
    start()
    非常不寻常。不要扩展
    线程
    ,而是实现
    可运行
    。重写
    Thread.start()
    可能会导致问题,这会阻止
    Thread
    在单独的线程中实际运行。不要这样做。顺便说一句,两条线打印的线的交错不是每次都不同。只是情况可能不同而已。我知道第一个线程总是在第二个线程开始之前运行到完成,这有点可疑,但仅此而已--可疑--这并不能证明Java运行时或操作系统有任何问题。@SolomonSlow我编辑了这篇文章,以便您可以看到它是什么。我也试过了,但没有覆盖开始。同样的结果
            t = new Thread (this, threadName);
            t.start ();