簡體   English   中英

同步方法不起作用,但同步塊起作用,為什么?

[英]Synchronized method does not work but synchronized block does, why?

public class driver{


public static void main(String[] args) {
    PrintNum firstObjectForThread = new PrintNum(0);  // the argument is not used, ignore it
    firstObjectForThread.startNewThread();

    PrintNum secondObjectForThread = new PrintNum(0);
    secondObjectForThread.startNewThread();

}

這是驅動程序調用的 class:

public class ClassName implements Runnable{

int variableForUpdate;
private Thread t;
private static ArrayList<Integer> intArray;

public ClassName(int variableForUpdate) {
    super();
    this.intArray = new ArrayList<Integer>();
    this.variableForUpdate = variableForUpdate;
    for (int i = 0; i < 30 ; i++) {
        this.intArray.add(i);
    }
}

@Override
public void run() {
    runThisWhenThreadStarts();
}


private synchronized void runThisWhenThreadStarts() {
    System.out.println("Started");
    for (int i = 0; i < 30; i++) {
        System.out.println(intArray.get(i));
    }
}

public void startNewThread() {
    t = new Thread(this);
    t.start();
}

}

如果我使用以下塊同步,則 output 是同步的:

private void runThisWhenThreadStarts() {
    synchronized (ClassName.class) {
        System.out.println("Started");
        for (int i = 0; i < 30; i++) {
            System.out.println(intArray.get(i));
        }
    }
}

我已經解決這個問題好幾個小時了,但無法弄清楚......有人能解釋一下嗎? 我還注意到,如果我使用相同的 object 調用 startNewThread(),同步將起作用。 但我不明白為什么。

    PrintNum firstObjectForThread = new PrintNum(0);  // the argument is not used, ignore it
    firstObjectForThread.startNewThread();
    firstObjectForThread.startNewThread();

我想使用來自同一個 class 的兩個不同的 object 而不是一個 object 調用該方法兩次(上述解決方法)。

我可以在另一個程序中使用同步方法,有 2 個不同的實例(get 和 put):

public class Hello extends Thread {
    int x;
    Coffee x1;
    int threadno;

    Hello(int x, Coffee x1) {
        this.x = x;
        threadno = x;
        this.x1 = x1;
    }

    public void run() {
        switch (x) {
        case 0:
            System.out.println("Start thread " + threadno + " Get");
            break;
        case 1:
            System.out.println("Start thread " + threadno + " Put");
            break;
        }
        ops();
        System.out.println("Stopping thread " + threadno);

    }

    public void ops() {
        x1.get();
    }

    public static void main(String[] args) {
        Coffee c1 = new Coffee();
        Hello get = new Hello(0, c1);
        Hello put = new Hello(0, c1);
        get.start();
        put.start();

    }
}

您好 class 將調用咖啡 class:

class Coffee {
    boolean available = false; // indicating there nothing to get.
    // waiting on each other.
    int contents = 55;

    public synchronized int get() {
        System.out.println("Entering Get method " + contents);
        for (int i = 0; i < 30; i++) {
            System.out.println(i);
            }
        return contents;
    }
}

在第一個示例中,該方法獲取調用該方法的 object 實例上的鎖。

該塊獲取 class 上的鎖。

對實例進行鎖定對其他線程沒有影響,它是不同的 object。 兩個線程都在獲取自己的鎖,這是沒有用的。 兩個線程都不能做任何事情。

獲取 class 上的鎖意味着兩個線程都試圖獲取相同的鎖。 為了使鎖定起作用,兩個線程必須使用相同的鎖定。

在第二個示例中,Coffee object 由兩個線程共享,並且兩個線程都試圖在 Coffee object 上獲取相同的鎖。 這意味着獲得鎖的第二個線程必須阻塞,直到第一個線程釋放鎖為止,鎖定成功使線程保持在外,直到第一個線程完成。

要了解同步,請跟蹤正在獲取哪些鎖。

暫無
暫無

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

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