首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

多線程面試經典題:Stack 同步實現隱藏的活鎖與通知遺漏缺陷

     編輯:Java 綜合教學

多線程面試經典題:Stack 同步實現隱藏的活鎖與通知遺漏缺陷

問題代碼

public class Stack {
    private LinkedList list = new LinkedList();

    public synchronized void push(Object x) {
        synchronized (list) {
            list.addLast(x);
            notify(); // 錯誤 1:鎖對象不一致
        }
    }

    public synchronized Object pop() throws Exception {
        synchronized (list) {
            if (list.size() <= 0) {
                wait(); // 錯誤 2:同樣鎖對象不一致
            }
            return list.removeLast();
        }
    }
}

核心缺陷分析

問題說明
鎖對象不一致方法用 synchronized(this),內部塊用 synchronized(list),notify()/wait() 作用於 this,但線程實際持有 list 鎖,導致通知遺漏
虛假喚醒wait() 應置於 while 迴圈而非 if
活鎖風險多生產者/消費者時,notify() 可能喚醒同類線程(生產者喚醒生產者),導致無效切換
異常處理wait() 拋出 InterruptedException 需處理

正確實現範例

public class StackFixed {
    private final LinkedList list = new LinkedList<>();
    private final int maxSize;

    public StackFixed(int maxSize) { this.maxSize = maxSize; }

    public synchronized void push(Object x) throws InterruptedException {
        while (list.size() >= maxSize) wait(); // while 防虛假喚醒
        list.addLast(x);
        notifyAll(); // 喚醒所有等待者
    }

    public synchronized Object pop() throws InterruptedException {
        while (list.isEmpty()) wait();
        Object x = list.removeLast();
        notifyAll();
        return x;
    }
}


關鍵修正點

  1. 統一鎖對象(方法鎖 this 即可,移除內部 synchronized(list))
  2. wait() 配合 while 判斷條件
  3. 使用 notifyAll() 避免活鎖
  4. 加入容量上限實現有界緩衝區

此題考察對監視器鎖、條件隊列、喚醒機制的深度理解。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved