由環形隊列消鎖引發的思考

來源:互聯網
上載者:User
我想,很多的程式員都知道如何利用環形隊列來避免使用鎖。那就是,生產者只更改寫指標,消費者只更改讀指標。當然這裡的指標一般可能是整數下標。例如: read_pos為消費者更改的讀指標,每讀走一個元素 則 read_pos = (read_pos + 1) % SIZE,            write_pos為生產者更改的寫指標,每寫完一個元素, write_pos = (write_pos + 1) % SIZE,在消費者看來,只要隊列不空,就可以讀取當前讀指標處的元素,在生產者看來,只要隊列不滿,就可以在當前的寫位置上寫一個元素。隊列為空白的條件為: read_pos = write_pos(對嗎?)隊列為滿的條件為: (write_pos + 1) % SIZE = read_pos(對嗎?)       現在所有的東西都已經考慮完了?       其實這種實現方案的最大的隱患在於如何能夠正確的比較read_pos和write_pos之間的關係。例如,很多人都覺得在read_pos = read_pos + 1執行完之前,read_pos會始終保持原來的值不變。這種錯誤很多人都會犯。可是又有人會反駁道,我就是這麼實現的,而且程式運行良好,從來沒出過問題。下面我們就講講,在什麼情況下,這種實現方法是正確的。這個我們必須得討論一下電腦的資料匯流排寬度。資料匯流排寬度標識這CPU一次能夠讀取的資料的大小。常見的有16位,32位,64位。現在我們討論一下read_pos與write_pos的類型,如果兩個都是int型,即都是32位,那麼如果你的電腦的資料匯流排寬度是32或64,那麼很幸運你將得到一個"不易出錯"的代碼,因為這種情況下read_pos或write_pos在完成加1操作之前一定是原來的值。而如果你的電腦資料匯流排寬度為16的話,我想你不出錯都很難,這時read_pos或write_pos在加1過程中很可能出現首先更改read_pos或write_pos的低16位,之後再更改它們的高16位。而恰恰如果我們在這兩次更改之間進行了讀,那麼讀到數肯定就會是錯誤的。那麼後果不言自明,這會導致判斷出現錯誤,因此,讀寫就會發生錯誤。同樣的問題會出現在read_pos和write_pos為long long類型,而卻應用在資料匯流排32位,16位機器上。       我們再回頭看看"不易出錯",說他不易出錯原因就是因為即使考慮了資料匯流排的寬度也是不全面的,因為我上面的代碼就是錯誤的。大家如果能仔細分析其實就不難猜到,隊列為空白或滿的判斷條件是不對的,應該改為隊列為空白:read_pos % SIZE = write_pos % SIZE隊列為滿:(write_pos + 1) % SIZE = read_pos % SIZE理由是,read_pos = (read_pos + 1) % SIZE,被編譯器分解為 read_pos = read_pos + 1, read_pos = read_pos % SIZE兩個操作,write_pos同理。那麼如果我們在第二個操作完成之前第一個操作完成之後讀取read_pos,那麼就讀到了錯誤的數,因為read_pos很可能等於SIZE。而我們卻規定read_pos與write_pos在0-SIZE-1之間。       當我寫到這的時候,您認為就已經考慮的足夠了嗎?答案是沒有。       我們還需要把read_pos和write_pos聲明為volatile,這個關鍵字的最主要用途就是防止編譯器最佳化,並且每次強制從記憶體中讀取值,而不是從寄存器。因為記憶體中的值才是最安全的。例如,如果電腦的加1操作被編譯器弄成了先+2後-1這種形式去實現,而+2之後的值存在寄存器中,而程式偏偏就在這時讀取了寄存器中的資料,那麼程式就會出錯。       寫到這,就接近尾聲了。對於環形隊列消鎖的問題可能並不存在十全十美的解決方案,即使考慮了上面的那些因素,也不能說明程式是正確的,因為我們不瞭解編譯器會怎麼做,也不瞭解電腦會怎麼做,我們這麼做只是讓我們的程式出錯的機率變小而已。而可能在現在的電腦體繫結構和作業系統以及編譯器恰好是對的,但是如果哪一天電腦的體繫結構變了,我們的系統可能會因上面的代碼隨時崩潰。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.