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

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

對單個靜態整數索引進行多次讀寫會導致索引越界

對單個靜態整數索引進行多次讀寫會導致索引越界

富國滬深 2023-07-13 17:45:51
我試圖學習多線程,并嘗試使用等待和通知的簡單生產者/消費者模式。當我將模式拆分為兩個消耗和一個產生時,我得到一個 ArrayIndexOutOfBounds 異常,該異常尚不清楚。該問題并不總是發生,有時會發生。我使用的是 I3 處理器。我嘗試添加一個 if 塊來檢查計數變量是否低于或高于聲明的大小,但問題仍然存在。    private static Object key = new Object();    private static int[] buffer;    private volatile static Integer count;    static class Consumer {        void consume() {            synchronized (key) {                if (isEmpty()) {                    try {                        key.wait();                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }                buffer[--count] = 0;                key.notify();            }        }        public boolean isEmpty() {            return count == 0;        }    }    static class Producer {        void produce() {            synchronized (key) {                if (isFull()) {                    try {                        key.wait();                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }                buffer[count++] = 1;                key.notify();            }        }        public boolean isFull() {            return count == buffer.length;        }    }    public static void main(String[] args) throws InterruptedException {        buffer = new int[10];        count = 0;        Producer producer = new Producer();        Consumer consumer = new Consumer();        Runnable produce = () -> {            for (int i = 0; i < 1500; i++)                producer.produce();            System.out.println("Done producing");        };        Runnable consume = () -> {            for (int i = 0; i < 1300; i++)                consumer.consume();            System.out.println("Done consuming");        };        };
查看完整描述

2 回答

?
拉莫斯之舞

TA貢獻1820條經驗 獲得超10個贊

問題是:

  • 對于“滿”和“空”狀態,您只有一個共享的等待條件

  • 您正在運行兩個消費者線程(“consumerWorker”和“delayedConsumer”)和一個生產者線程(“ ProducerWorker”)

  • 你沒有像你應該的那樣重新檢查 while 循環中的條件

可能發生的事情是:

  1. 兩個消費者線程都看到緩沖區為空

  2. 生產者線程將一項放入緩沖區并發出通知。

  3. 單個消費者線程喚醒并處理一項。緩沖區現在是空的。然后它會發出通知。

  4. 第二個消費者線程醒來(而不是像您預期的那樣的生產者),不檢查緩沖區是否為空,并嘗試訪問索引 -1 處的緩沖區。

您從通話中醒來后需要重新檢查情況wait。將 更改ifwhile.?以下是如何為消費者做到這一點;您需要為制作人做同樣的事情。

? ? void consume() {

? ? ? ? synchronized (key) {

? ? ? ? ? ? while (isEmpty()) {

? ? ? ? ? ? ? ? try {

? ? ? ? ? ? ? ? ? ? key.wait();

? ? ? ? ? ? ? ? } catch (InterruptedException e) {

? ? ? ? ? ? ? ? ? ? e.printStackTrace();

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? ? buffer[--count] = 0;

? ? ? ? ? ? key.notify();

? ? ? ? }

? ? }

這樣消費者就不會被來自notify其他消費者線程的 所迷惑。


查看完整回答
反對 回復 2023-07-13
?
函數式編程

TA貢獻1807條經驗 獲得超9個贊

你的緩沖區長度為 10

buffer = new int[10];

因此,每當您的計數變量超過數組容量(即 10)時,就會很明顯

    private volatile static Integer count;

你會得到ArrayIndexOutOfBoundsException

您生產更多,消耗更少,消耗更少,并且生產/消費的執行不是順序的,它更像是循環。


查看完整回答
反對 回復 2023-07-13
  • 2 回答
  • 0 關注
  • 141 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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