【问题标题】:Java Threads Object LockJava 线程对象锁
【发布时间】:2018-12-10 16:56:11
【问题描述】:

根据我的理解,每个对象都有一个可以被当前线程持有的锁。

所以,基于这个例子:

public class T1 {
    private final Object o = new Object();

    public  void m1() {
        synchronized(o) {
            //...wait some time
        }
    }
}

如果我创建类似的东西:

    T1 subject1 = new T1();
    T1 subject2 = new T1();
    Runnable r1 = new Runnable() {
        @Override
        public void run() {
            subject1.m1();
            subject2.m1();  
        }
    };

Thread t1 = new Thread(r1);
t1.start();

会有两个锁,subject1.osubject2.o(我测试它们是不同的实例),这意味着这两种方法将独立运行,同时,在我的例子中,一个被执行,然后,它释放锁,下一个运行虽然 subject1 和 subject2 是具有不同锁的不同实例。

为什么?

【问题讨论】:

  • subject1 和subject1 都是T1 extends Object 的实例,因此,如果你通过调用synchronize 对object 加锁,它们会按照获取锁的顺序处理...
  • 但是每个实例都包含自己的锁,不是吗?那么,为什么这些行为看起来像是共享同一个锁呢?
  • 它们扩展了同一个对象,两者都有权锁定。类对象是类层次结构的根。每个类都有 Object 作为超类。所有对象,包括数组,都实现了这个类的方法。因此,如果 subject1 获得了 Object 上的锁定,它不会允许其他人访问它(同步负责),直到它完成它的工作。
  • 好的,两个类都扩展了 Object,但是在实例级别上讲,两个 Object 父级的类也不同。如果您在 Class 级别进行讨论,那么任何其他对象的任何其他实例也将被锁定。这里的重点是为什么即使使用不同的 T1 实例,由于它们具有不同的锁对象实例,它们也会相互阻塞。

标签: java multithreading


【解决方案1】:

在您的示例中,您在同一线程中按顺序运行这两种方法。要并行执行它们,您必须在单独的线程中运行它们。

T1 subject1 = new T1();
T1 subject2 = new T1();
Runnable r1 = new Runnable() {
    @Override
    public void run() {
        subject2.m1();  
    }
};
Runnable r2 = new Runnable() {
    @Override
    public void run() {
        subject2.m1();  
    }
};

Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();

【讨论】:

  • @Eduardo,在您的示例中,锁不会相互阻塞。他们只是在第二个方法开始执行之前运行第一个方法完成。
【解决方案2】:

会有两个锁,subject1.osubject2.o ...,这意味着这两个方法将同时独立运行。

没有。有两个锁的事实意味着对m1 函数的两次调用将同时独立运行。这只意味着两个调用可以同时运行。但这只有在这两个调用中的每一个都发生在不同的线程中时才会发生。

这里已经尝试告诉您的其他答案是,您的代码不会从两个不同的线程进行两次调用。它从同一个线程进行两次调用。你写了这个 run() 方法:

public void run() {
    subject1.m1();
    subject2.m1();  
}

run() 方法没有什么特别之处。 写了它,它的工作方式与你写的任何其他方法完全一样:你写的方法将首先调用subject1.m1(),然后当它返回时,它会调用subject2.m1()

如果您想并行进行这些调用,请按照 @Palamino 或 @snr 向您展示的操作。

【讨论】:

    【解决方案3】:

    会有两个锁,subject1.osubject2.o(我测试过它们 是不同的实例),这意味着 两种方法都将运行 独立同时

    您说这两种方法都将独立运行,尽管您只有一个封闭方法来运行两个线程。相反,这两种方法必须在不同的Runnables 中才能同时执行。

    T1 subject1 = new T1();
    T1 subject2 = new T1();
    Runnable r1 = subject1::m1;
    Runnable r2 = subject2::m1;
    Thread t1 = new Thread(r1);
    Thread t2 = new Thread(r2);
    t1.start();
    t2.start();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-05-31
      • 2017-11-05
      • 2020-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多