簡體   English   中英

不同對象上的同步語句可以交錯嗎?

[英]Can synchronized statements on different objects interleave?

我正在研究關鍵字synchronized ,我不明白是否可以在同一個 class 中有 2 個同步語句來交錯; 例子:

我用這些簡單的方法和兩個鎖對象做了一個 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);
            }
        }
    }
}

我創建了兩個不同的線程,它們只調用printL1printL2 ,據我了解,我認為因為這是兩個不同的鎖,我會看到交替打印正數和負數,因為並發是可能的,但我嘗試了很多次並且printL2總是在printL1之后完全發生,沒有一次我在正數之間看到負數,我是否在同步時遺漏了一些東西?

這是代碼的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();
    }   
}

和主要的 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();
    }
}

你對線程和鎖的理解是正確的。 由於Locker1.printL1()Locker1.printL2()將鎖授予不同的對象,一個線程訪問Locker1.printL1()而另一個訪問Locker1.printL2()不應相互阻塞。

您在 printL1 之后看到完整的 printL2 結果的原因是因為 CPU 的工作量太少。 50 次迭代只需幾分之一毫秒即可完成。 在需要上下文切換之前,任務已經完成。

讓任務休眠一小段時間,你就可以看到線程是如何產生的。

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:

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

交錯按預期發生; 只有 50 次迭代很難看到,所以進行更多的迭代就可以看出這一點

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM