日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

netty之wakeup详解

發布時間:2023/12/20 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 netty之wakeup详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

有關wakeup變量的使用有一下幾個地方(這里只使用netty普通任務舉例,不討論定時任務)

部分1,NioEventLoop.select()

if (hasTasks() && wakenUp.compareAndSet(false, true)) {selector.selectNow();selectCnt = 1;break;}int selectedKeys = selector.select(timeoutMillis);selectCnt ++;if (selectedKeys != 0 || oldWakenUp || wakenUp.get() || hasTasks() || hasScheduledTasks()) {break;}

部分2 NioEventLoop.run()

select(wakenUp.getAndSet(false));if (wakenUp.get()) {selector.wakeup();}

部分3 NioEventLoop.wakeup()

protected void wakeup(boolean inEventLoop) {if (!inEventLoop && wakenUp.compareAndSet(false, true)) {selector.wakeup();}}

1,2是reactor線程進行操作的方法 3是用戶線程操作的方法
方法三比較好理解,就是在添加完一個任務后,去修改這個wakeup變量,然后去喚醒這個reactor線程

首先關注2,值得注意的是getAndSet返回的是修改之前的值,但是在這個select(wakenUp.getAndSet(false))之后又調用了一次selector.wakeup(); 為什么要這樣做呢???

舉例:

情況一
wakeup此時為默認值,但是現在用戶線程在select(wakenUp.getAndSet(false)) 之前 修改wakeup為 true,調用了 wakeup()
此時傳入select(wakenUp.getAndSet(false))的參數oldwakeup為 true ,wake的最新值,筆者稱為newwakeup 這里為 false
因為用戶線程調用了wakeup(),所以阻塞的select 方法不會阻塞
所以成功的沒有進過阻塞進入break 因為沒有阻塞,這種情況我稱為喚醒成功

情況二
但是現在用戶線程在select(wakenUp.getAndSet(false)) 之后 修改wakeup會失敗,wakeup()不會調用
select(wakenUp.getAndSet(false))的參數oldwakeup為 false,newwakeup 為true
在部分1中if (hasTasks() && wakenUp.compareAndSet(false, true)) 這個判斷會進入,然后調用了一次selectNow(),然后就break了
沒有阻塞,喚醒成功

以上兩中情況,針對的是第一次遍歷執行
下面進入第二次遍歷執行
當上面的情況被喚醒后,就會來到 if (wakenUp.get()) 這個判斷,這里如果是被喚醒過來的,這里就會為true,又調用了一次wakeup
那么當再次進入oldwakeup為true,newwakeup為false,所以又重復了第一次遍歷中的第一種情況,那么為什么要這么做???
加入netty在第二次遍歷的時候又進來的一個任務呢?此時是沒有辦法調用到wakeup()這個方法的,因為調用這個方法之前有一個判斷
wakenUp.compareAndSet(false, true),這個判斷不會通過,而部分2中的wakeup()就是解決這個情況的

對于后面的遍歷,如果沒有設計到喚醒操作,那么oldwakeup 和 newwakeup都是false,netty就會進入正常的輪詢了

那么現在又有一個問題,為什么需要使用到wakeup這個變量?
通過這個變量的類型可以知道 wakeup 是 AtomicBoolean,所以一定是為了解決并發問題的,如果說多個線程都需要喚醒操作本來是需要執行多次wakeup()這個操作的,但是wakeup()是個耗時的操作,所以使用到AtomicBoolean的compareAndSet(expect, update)方法,使得多次wakeup()都合并成一個wakeup()

總結

以上是生活随笔為你收集整理的netty之wakeup详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。