【问题标题】:Can synchronized statements on different objects interleave?不同对象上的同步语句可以交错吗?
【发布时间】:2020-06-08 08:47:30
【问题描述】:

我正在研究关键字synchronized,我不明白是否可以在同一个类中有2个同步语句进行交错;示例:

我用这些简单的方法和两个锁对象创建了一个类:

public class Locker1 {  
    private Object lock1= new Object();
    private Object lock2= new Object();

    public void printL1() {
        synchronized(lock1) {
            for(int i=0; i<50;i++) {
                System.out.println(i);
            }
        }
    }

    public void printL2() {
        synchronized(lock2) {
            for(int i=0; i<50;i++) {
                System.out.println("-"+i);
            }
        }
    }
}

我创建了两个不同的线程,分别调用 printL1printL2,据我了解,我认为因为这是两个不同的锁,我会看到交替打印正数和负数,因为并发是可能的,但我尝试了很多次并且printL2 总是完全在 printL1 之后发生,而不是在我看到正数之间出现负数时,我是否在同步时遗漏了什么?

这是剩下的代码

public class ThreadA extends Thread {
    private Locker1 l1;

    public ThreadA(Locker1 l1) {
        this.l1=l1;
    }

    public void run() {
        l1.printL1();
    }
}
public class ThreadB extends Thread {   
    private Locker1 l1;

    public ThreadB(Locker1 l1) {
        this.l1=l1;
    }

    public void run() {
        l1.printL2();
    }   
}

和主类:

public class Main {
    public static void main(String[] args) {
        Locker1 l1=new Locker1();

        ThreadA tA=new ThreadA(l1);
        ThreadB tB=new ThreadB(l1);
        tA.start();
        tB.start();
    }
}

【问题讨论】:

  • 请显示调用您的打印方法的代码
  • 你能告诉我们你是如何使用这个类的吗?
  • @Lino ok 添加了希望不会太长
  • 你尝试过更多的迭代吗? 50 次迭代可以在第二个线程开始运行之前简单地完成。您的代码看起来不错
  • 很有趣,我已经用代码尝试了一个东西 - 在 tA.start() 之前移动了 tB.start()。但是,正数仍然首先出现。 JVM 在幕后做了一些有趣的事情。

标签: java locking synchronized


【解决方案1】:

你对线程和锁的理解是正确的。由于Locker1.printL1()Locker1.printL2() 将锁授予不同的对象,一个线程访问Locker1.printL1() 而另一个访问Locker1.printL2() 不应相互阻塞。

您在 printL1 之后看到完整的 printL2 结果的原因是因为 CPU 的工作量太少。 50 次迭代需要几分之一毫秒才能完成。在需要 context switch 之前,任务已完成。

让任务休眠一小段时间,你可以看到线程是如何屈服的。

public class Locker1 {
    private Object lock1 = new Object();
    private Object lock2 = new Object();

    public void printL1() {
        synchronized (lock1) {
            for (int i = 0; i < 50; i++) {
                System.out.println(i);
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }

    public void printL2() {
        synchronized (lock2) {
            for (int i = 0; i < 50; i++) {
                System.out.println("-" + i);
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
}

输出:

0
-0
1
-1
2
-2
3
-3
4
-4
5
-5
6
-6
7
-7
8
-8
9
-9
10
-10
11
-11
12
-12
13
-13
14
-14
15
-15
16
-16
17
-17
18
-18
19
-19
20
-20
21
-21
22
-22
-23
23
24
-24
25
-25
26
-26
27
-27
28
-28
29
-29
30
-30
31
-31
32
-32
33
-33
34
-34
35
-35
36
-36
37
-37
38
-38
39
-39
40
-40
41
-41
42
-42
43
-43
44
-44
45
-45
46
-46
47
-47
48
-48
49
-49

【讨论】:

    【解决方案2】:

    交错按预期发生;仅 50 次迭代就很难看到,因此进行更多迭代即可显示它

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-26
      • 1970-01-01
      • 2020-06-28
      • 1970-01-01
      • 1970-01-01
      • 2016-01-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多