【问题标题】:Why is Java synchronized not working as expected?为什么 Java 同步没有按预期工作?
【发布时间】:2017-05-26 15:56:54
【问题描述】:

我试图弄清楚同步方法是如何工作的。据我了解,我创建了两个线程 T1T2,它们将调用相同的方法 addNew,因为该方法是同步的,它不应该执行 for 的所有迭代吗?循环一个线程然后另一个?输出不断变化,有时会正确打印,有时会打印 T1 中的值与 T2 值混合。代码很简单,谁能指出我做错了什么?谢谢。

public class Main {
    public static void main(String[] args) {
        Thread t1 = new Thread(new A());
        Thread t2 = new Thread(new A());
        t1.setName("T1");
        t2.setName("T2");
        t1.start();
        t2.start();
    }
}

public class B {
    public synchronized void addNew(int i){
        Thread t = Thread.currentThread();
        for (int j = 0; j < 5; j++) {
            System.out.println(t.getName() +"-"+(j+i));
        }
    }
}

public class A extends Thread {
    private B b1 = new B();

    @Override
    public void run() {
        b1.addNew(100);
    }
}

【问题讨论】:

标签: java multithreading synchronized


【解决方案1】:

每个A 实例都有自己的B 实例。方法addNewB 的实例方法。因此,在调用addNew 期间隐式获取的锁是接收者B 实例上的锁。每个线程在不同的B 上调用addNew,因此锁定不同的锁。

如果您希望所有 B 实例使用公共锁,请创建一个共享锁,并在addNew 的主体中获取它。

【讨论】:

  • 谢谢,我该如何创建一个共享锁?
  • 每个对象都可以充当锁,因此只需创建一个在所有B 实例之间共享的对象即可。 private static final Object lock = new Object().
  • 或者将相同的Runnable实例传递给每个线程,这是经常做的。
【解决方案2】:

两个A 对象都有自己的B 对象。您需要他们分享B,以便同步生效。

【讨论】:

    【解决方案3】:

    试试这个:

    public class Main {
        public static void main(String[] args) {
            A a = new A();
            Thread t1 = new Thread(a);
            Thread t2 = new Thread(a);
            t1.setName("T1");
            t2.setName("T2");
            t1.start();
            t2.start();
        }
    }
    
     class B {
        public synchronized void addNew(int i){
            Thread t = Thread.currentThread();
            for (int j = 0; j < 5; j++) {
                System.out.println(t.getName() +"-"+(j+i));
            }
        }
    }
    
     class A extends Thread {
        private B b1 = new B();
    
        @Override
        public void run() {
            b1.addNew(100);
        }
    }
    

    【讨论】:

    • 问题中要求的解释在哪里?另外,这如何改变执行?请解释一下。
    • 为了同步,线程需要锁定对象才能完全执行。当它完成同步代码的执行时,它会离开对象,然后同一个对象被另一个线程锁定并执行,从而实现同步。为此,必须在创建 Thread 对象时将相同的对象作为争论传递。帖子作者使用“new A()”作为arguemnet创建线程对象,那种传递两个不同的对象。所以没有实现同步。
    • 对不起,我不清楚。我的意思是让你把它添加到你的帖子中:)
    猜你喜欢
    • 2014-12-24
    • 2015-05-06
    • 2014-08-04
    • 2021-01-03
    • 2018-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多