Java多线程同步(对象)

Java多线程同步(对象),java,multithreading,deadlock,Java,Multithreading,Deadlock,我有3节课,如下所示。我使用了synchronized(b)因此,一个对象获得了b对象上的锁,并且在A中的foo方法完成工作之前,不会调用b中的任何方法 但是,这似乎不起作用(见最后的输出)。实际上,racethread能够调用对象b上的方法 注意:您可以创建一个简单的java项目,并在一个文件中添加以下代码以尝试执行 包com.threads.main.deadlock class A { void foo(B b) { synchronized (b) { // Tr

我有3节课,如下所示。我使用了
synchronized(b)
因此,一个对象获得了b对象上的锁,并且在
A
中的
foo
方法完成工作之前,不会调用b中的任何方法

但是,这似乎不起作用(见最后的输出)。实际上,
racethread
能够调用对象b上的方法

注意:您可以创建一个简单的java项目,并在一个文件中添加以下代码以尝试执行

包com.threads.main.deadlock

class A {
    void foo(B b) {
        synchronized (b) { // Trying to get lock on b here
            String name = Thread.currentThread().getName();
            System.out.println(name + " entered A.foo");
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
                System.out.println("A Interrupted");
            }
            System.out.println(name + " trying to call B.last()");
            b.last();
        }
    }

    synchronized void last() {
        System.out.println("Inside A.last");
    }
}
class B {
    void bar(A a) {
        synchronized (a) {

            String name = Thread.currentThread().getName();
            System.out.println(name + " entered B.bar");
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
                System.out.println("B Interrupted");
            }
            System.out.println(name + " trying to call A.last()");
            a.last();
        }
    }

    synchronized void last() {
        System.out.println("Inside B.last");
    }
}
public class Deadlock implements Runnable {
    A a = new A();
    B b = new B();

    Deadlock() {
        Thread.currentThread().setName("MainThread");
        Thread t = new Thread(this, "RacingThread");
        t.start();

        new Thread(new Dum(a)).start();
        a.foo(b); // get lock on a in this thread.
        System.out.println("Back in main thread");
    }

    public void run() {
        b.bar(a); // get lock on b in other thread.
        System.out.println("Back in other thread");
    }

    public static void main(String args[]) {
        new Deadlock();
    }
}

class Dum implements Runnable {

    A a = null;

    public Dum(A a) {
        this.a = a;
    }

    @Override
    public void run() {
        int i =0; 
        while (i++ < 5) {
            System.out.println("Trying a.last .. dum");
            a.last();
        }
    }

}

A线程和B线程在其方法中使用不同的对象进行同步

那么你的假设呢

对象获得B对象上的锁,而B中没有任何方法 将被调用,直到A中的foo方法完成工作

这是错误的。当A.foo运行时,它使用B的实例进行同步。但是,这只会阻止B.last的并行运行,因为B.foo在a上有一个同步块。但是,当a.foo尝试调用B.last时,它不会导致任何阻塞,因为a.foo已经在B的监视器中

如果您有这样的方法:

synchronized void last() {
}
这基本上相当于:

void last() {
   synchronized(this){ //so in case of Class B it means: this = the B instance
   }
}

我建议您命名所有线程,并将Thread.currentThread().getName()添加到每个系统中,这样您就会更好地理解它。

您在这里的期望值真的不清楚;没有什么会导致死锁。可能是另一种误解,即两个线程需要在同一个对象监视器上同步才能同步,并且无法“锁定对象”。@Kayaman,能否请您在“两个线程需要在同一个对象监视器上同步才能同步”上进行eloborate?能否请您修改类并显示它。这很难理解,因为我是多线程新手。另外,下一个点,当我添加同步(对象)时,对象将被刚刚进入对象监视器的线程锁定;在线程释放监视器之前,锁定对象中的任何方法都不会被其他线程访问?@BrianRoach我希望foo()对象在保持B上的方法锁定的同时完成执行,在我执行完foo()之后,其他线程可以调用对象B上的方法。但是,根据我在控制台中打印的输出语句,我无法锁定对象B。您描述的正是发生的情况。您在A的实例上进行了同步,休眠了一秒钟,名为
A.last()
,然后释放。当这种情况发生时,您的
Dum
runnable在
a.last()上阻塞
void last() {
   synchronized(this){ //so in case of Class B it means: this = the B instance
   }
}