一個讓Netty作者也感到驚訝的錯誤

為了表示我不是標(biāo)題黨,先來個截圖:


圖片發(fā)自簡書App

Netty是Java世界里網(wǎng)絡(luò)編程框架的明星,也是我非常喜歡和推崇的開源項目之一。但其核心的Future接口實現(xiàn)卻犯了一個基本的邏輯錯誤,本文就指出了Netty中的核心Future接口在實現(xiàn)cancel和isDone方法時違反了約定規(guī)則的問題。

首先來看java.util.concurrent.Future#cancel方法的javadoc約定:

After this method returns, subsequent calls to isDone will always return true.

就是說,在調(diào)用了cancel方法后,再調(diào)用isDone將永遠(yuǎn)返回true。

Netty的Future接口繼承了Java的Future接口:

public interface Future<V> extends java.util.concurrent.Future<V>

所以在實現(xiàn)的時候理應(yīng)遵循這一約定,但Netty截止到目前的最新版本中(4.1.21),并沒有遵循這一約定,參見下面的代碼例子:

import io.netty.util.concurrent.GlobalEventExecutor;

import io.netty.util.concurrent.Promise;

public class DefaultPromiseIsDoneTest {

    private final Promise defaultPromise = GlobalEventExecutor.INSTANCE.newPromise();

    public static void main(String args[]) {

        DefaultPromiseIsDoneTest main = new DefaultPromiseIsDoneTest();

        main.isDoneTest();

    }

    private void isDoneTest() {

        defaultPromise.setUncancellable();

        defaultPromise.cancel(false);

        boolean isDone = defaultPromise.isDone();

        System.out.println(isDone);

    }
}

運行后,控制臺打印的是 false。 而按照約定,應(yīng)該打印true才對。

Netty其它幾個實現(xiàn)類也沒有遵循這一約定:

io.netty.channel.group.VoidChannelGroupFuture#isDone
io.netty.channel.VoidChannelPromise#isDone

我在Netty的github上提出了這個問題,得到了Netty官方的確認(rèn)。

https://github.com/netty/netty/issues/7712

但由于修改會導(dǎo)致當(dāng)前版本用戶受到影響,所以Netty準(zhǔn)備在下一個大版本中修復(fù)這一問題。

我們在異步編程,實現(xiàn)Future接口的時候,對cancel和isDone方法的理解很可能會依賴于直覺,而沒有嚴(yán)格對照接口文檔中約定的邏輯來實現(xiàn)。甚至像Netty這樣的老司機也犯了大意的錯誤。特寫出這篇文章,跟大家共勉。

具體的討論可以參見我的stackoverflow帖子(本文開頭的圖片就截自下面的帖子):

does-netty-violate-the-contract-of-future-cancel-method

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容