亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

什么時候應該使用同步方法,什么時候應該在 Java 中使用同步塊?

什么時候應該使用同步方法,什么時候應該在 Java 中使用同步塊?

胡說叔叔 2022-05-21 13:07:16
我正在研究如何在 Java 中同步方法和塊以避免競爭條件,我試圖以兩種方式解決一個練習。問題是,如果我嘗試使用同步塊,一切正常,但使用同步方法會卡住。我認為我可以使用兩種方式而沒有太大的差異(也許其中一種方式在某些情況下會降低并行性,但我不確定這一點)。我想知道我的代碼有什么問題,我想問一下是否有任何情況下最好使用同步塊而不是同步方法。//不工作import java.util.Random;class MultiplicationTable extends Thread {    private Cont obj;    private int number;    private Random r;    public MultiplicationTable(Cont o, int num) {        obj = o;        number = num;        r = new Random();        start();    }    public void run() {        for (int j = 0; j < 10; j++) {            for (int i = 0; i < number; i++) {                obj.incr();                try {                    Thread.sleep(100);                } catch (InterruptedException e) {                }            }            System.out.println(Thread.currentThread().getName() + ": " + obj.getVal());        }        try {            Thread.sleep(r.nextInt(2000));        } catch (InterruptedException e) {        }    }}class Cont {    private int count = 0;    private boolean available = false;    public synchronized void incr() {        while (available) {            try {                wait();            } catch (InterruptedException e) {                // TODO: handle exception            }        }        available = true;        count++;        notifyAll();    }    public synchronized int getVal() {        while (!available) {            try {                wait();            } catch (Exception e) {                // TODO: handle exception            }        }        available = false;        notifyAll();        return count;    }}public class Es3 {    public static void main(String[] args) {        Cont obj = new Cont();        int num = 5;        MultiplicationTable t1 = new MultiplicationTable(obj, num);        MultiplicationTable t2 = new MultiplicationTable(obj, num);    }}
查看完整描述

2 回答

?
慕森王

TA貢獻1777條經驗 獲得超3個贊

我不認為這是一個騙局,因為盡管有標題,但實際問題是 OP 的具體實現。代碼中有一個錯誤,這不是方法與塊的問題。


代碼中的錯誤是您嘗試實現鎖定機制的地方。在incr()中,您等到available設置為 false,這僅發生在getVal():


public synchronized void incr() {

    while (available) { // <-- bug

        try {

            wait();

由于您的循環只調用incr()而不調用getVal(),因此兩個線程在第一次調用incr(). (你getVal()最終會調用,但只有在內循環完成之后。兩個線程都很好并且到那時卡住了。)


解決方案:AtomicInteger沒有像這樣的奇怪錯誤。如果您嘗試實現某種生產者/消費者機制,那么其中一個并發隊列(如ArrayBlockingQueue)是更好的解決方案。


查看完整回答
反對 回復 2022-05-21
?
jeck貓

TA貢獻1909條經驗 獲得超7個贊

  1. 同步方法之間的一個顯著區別是,同步塊通常會減少鎖定范圍。由于鎖定范圍與性能成反比,因此只鎖定代碼的關鍵部分總是更好。使用同步塊的最佳示例之一是 Singleton 模式中的雙重檢查鎖定,getInstance()我們只鎖定用于創建 Singleton 實例的代碼的關鍵部分,而不是鎖定整個方法。這極大地提高了性能,因為鎖定只需要一兩次。

  2. 同步塊提供了對鎖的精細控制,因為您可以使用任意鎖來為關鍵部分代碼提供互斥。另一方面,同步方法總是鎖定由 this 關鍵字表示的當前對象或類級別鎖定,如果它的靜態同步方法。

  3. 如果作為參數提供給塊的表達式計算為 null,則同步塊可以拋出 throw java.lang.NullPointerException,而同步方法則不是這種情況。

  4. 在同步方法的情況下,線程進入方法時獲取鎖,離開方法時釋放鎖,正?;驋伋霎惓?。另一方面,在同步塊的情況下,線程進入同步塊時獲取鎖,離開同步塊時釋放。


查看完整回答
反對 回復 2022-05-21
  • 2 回答
  • 0 關注
  • 148 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號