简体   繁体   English

不同对象上的同步语句可以交错吗?

[英]Can synchronized statements on different objects interleave?

I am studying the keyword synchronized and I do not understand if it's possible to have 2 synchronized statements in the same class to interleave;我正在研究关键字synchronized ,我不明白是否可以在同一个 class 中有 2 个同步语句来交错; example:例子:

I made a class with these simple methods and two lock objects:我用这些简单的方法和两个锁对象做了一个 class:

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);
            }
        }
    }
}

I made two different threads that just call printL1 and printL2 , in my understanding I thought since these are two different locks I would see positive and negative numbers printed alternatively because concurrency is possible, but I tried many times and printL2 always happens entirely after printL1 , not once I saw a negative between positive numbers, am I missing something on synchronized?我创建了两个不同的线程,它们只调用printL1printL2 ,据我了解,我认为因为这是两个不同的锁,我会看到交替打印正数和负数,因为并发是可能的,但我尝试了很多次并且printL2总是在printL1之后完全发生,没有一次我在正数之间看到负数,我是否在同步时遗漏了一些东西?

Here is the rest of the code这是代码的rest

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();
    }   
}

and main class:和主要的 class:

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();
    }
}

You understanding on Thread and Lock is correct.你对线程和锁的理解是正确的。 Since Locker1.printL1() and Locker1.printL2() grant the lock to different objects, One thread access Locker1.printL1() while another access Locker1.printL2() should not block each other.由于Locker1.printL1()Locker1.printL2()将锁授予不同的对象,一个线程访问Locker1.printL1()而另一个访问Locker1.printL2()不应相互阻塞。

The reason you see a complete printL2 result after printL1 is because the work is too little for the CPU.您在 printL1 之后看到完整的 printL2 结果的原因是因为 CPU 的工作量太少。 50 iterations take a fraction of millisecond to complete. 50 次迭代只需几分之一毫秒即可完成。 Before a context switch is needed, the task is completed.在需要上下文切换之前,任务已经完成。

Let the task sleep for a small amount of time and you can see how the thread yield.让任务休眠一小段时间,你就可以看到线程是如何产生的。

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();
                }
            }
        }
    }
}

output: output:

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

The interleaving happens as expected;交错按预期发生; it was hard to see with only 50 iterations, so putting in a lot more iterations shows it只有 50 次迭代很难看到,所以进行更多的迭代就可以看出这一点

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM