国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > iOS > 正文

IOS 實現一個死鎖導致 UI 假死的例子

2019-10-21 18:49:17
字體:
來源:轉載
供稿:網友

IOS 實現一個死鎖導致 UI 假死的例子

現象

當 APP 啟動一段時間后(約半小時左右),經常會發現 App 界面出現“凍死”的現象。同時后臺輸出:

[CocoaGoPush]WorkThreadProc end

這時 App 呈現“假死”狀態,點擊屏幕任何地方沒有反應,iPhone 除了開屏關屏無任何響應(包括按 Home 鍵),當然也無法解鎖(但可以重啟)。如果用 Xcode 終止應用程序,則 iPhone 又恢復正常。

注:App 使用了 CocoaGoPush 框架。

發現

原來以為是程序主線程中產生了死循環,導致 UI 無反應。但當我點擊 Debug 工具欄中的 Pause 按鈕,列出當前運行的線程時,則發現問題并不是這樣,而是用于死鎖。調試暫停后,斷點停在了這一句:

app.gopushLock.lock()// MARK: yhy removed 這行導致主線程死鎖

app.gopushLock 是一個 NSRecursiveLock 對象:

let gopushLock = NSRecursiveLock()

NSRecursiveLock 是遞歸鎖,該類鎖可以在同一線程多次請求一個鎖時,不會引起死鎖。但如果程序員錯誤地在兩個線程中使用了遞歸鎖,則很容易導致“死鎖”出現:兩個線程同時對同一個鎖進行加鎖,同時發現該鎖已經鎖定,彼此等待對方解鎖,導致兩個線程都無法執行下去。尤其是有一方是主線程的情況下,主線程被阻塞,UI 呈現假死狀態。在這個例子中還發現,gopush 所在的線程也停止了,不再繼續監聽 gopush 消息和維持心跳。

檢查代碼發現,代碼在另一個地方使用了這個遞歸鎖:

NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler:{      (response, data, error) -> Void in      if (error != nil) {        app.gopushLock.lock()        app.isGoPushFetchingMessage = false        app.gopushLock.unlock()        println("-----------GoPush Message Guard fail to fetch offline message. err = /(error.localizedDescription)-----------")        ... })

NSURLConection.sendAysnchronousRequest 方法導致請求在新的線程中發送,因此 app.gopushLock.lock() 實際上是在子線程中調用的。而另外一處(第一段代碼)則是在主線程中調用的,因此導致了“競爭”。

解決

方法一

將主線程中的遞歸鎖調用注釋,只留下子線程中的遞歸鎖調用。

方法二

在主線程中采用不同的鎖,比如重新定義一個 NSLock 專門用于主線程,和子線程中的 gopushLock 區別開來。

方法三

將 gopushLock 的類型由 NSRecursiveLock 改為 NSLock。顧名思義,遞歸鎖專門用于循環或遞歸中需要同步的代碼,但它卻不能避免兩個線程同時訪問鎖中代碼的情況。而 NSLock 卻恰恰相反,它能避免兩個線程同時訪問鎖中的代碼,卻不能避免在同一線程中,同步代碼中嵌套加鎖的情況。檢查第二段調用遞歸鎖的情況,發現這里根本沒有必要使用遞歸鎖,因為代碼中既沒有遞歸也沒有循環。因此可以放心地將 gopushLock 修改為 NSLock 而不是 NSRecursiveLock。

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!


注:相關教程知識閱讀請移步到IOS開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 金堂县| 高雄市| 长治县| 绵竹市| 瓦房店市| 双江| 沙坪坝区| 安塞县| 舞钢市| 叶城县| 樟树市| 东平县| 开平市| 灵璧县| 舞阳县| 宁城县| 会宁县| 灵璧县| 云南省| 东台市| 连南| 韶关市| 贺兰县| 繁峙县| 息烽县| 启东市| 黄浦区| 芮城县| 株洲县| 西充县| 萍乡市| 彰武县| 本溪| 台中市| 漳浦县| 纳雍县| 万盛区| 朔州市| 察隅县| 石首市| 璧山县|