亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

iOS使用多線程提高數據并發訪問 之六

發布時間:2020-06-30 06:25:07 來源:網絡 閱讀:1756 作者:iKingLai 欄目:移動開發

線程的風險


當運行在一個多線程環境中,你總是需要注意一些事情:你不能控制線程執行的順序。例如,如果你有兩個線程,線程1和線程2,CPU可能會在線程1上運行一段時間,然后又會切到線程2運行一段時間。問題是你不知道CPU何時切過去,也不知道會為一個線程分配多少時間。每個線程運行的時間都不是公平的。


為了演示線程不容易控制帶來的風險,我會舉一個例子。這個例子包括兩個線程:線程1和線程2. 線程1打印奇數,線程2打印偶數。這些數的范圍從1到20. 線程1先啟動,然后線程2再啟動。這個例子將會運行3次。Listing 6-5 顯示了樣例代碼。


iOS使用多線程提高數據并發訪問 之六


正如你看到的,我先調用打印奇數,然后再打印偶數。你可能會期待看到

  • 先打印一些奇數

  • 奇數和偶數平均打印,例如兩個奇數和兩個偶數


但是,這些猜測都是不正確的,你可以看表格 6-4, 顯示了3次運行的結果。


iOS使用多線程提高數據并發訪問 之六


你看下第2次,0先打印出來,而其他的都是先打印1。奇數和偶數打印也不是平均的;而且,也沒什么跡象表明有多少奇數在偶數之前打印。


因此,在多線程環境中,你不能控制線程執行的順序。多線程是一把雙刃劍。開發者實現一個多線程應用需要注意下面的3個風險。

  • 安全性:這個標準意味著在多線程環境下,輸出要跟預期的一致。換句話說,程序可以運行在不同的順序中多次,但是最終的輸出必須是可預見的,正確的。“糟糕的事情不會發生”。

  • 活躍性:這個和安全性不同。一種定義是“一些好的情況最終會發生”。例如,假設線程A必須等到線程B的結果,有時這些結果從來都不返回。因此,線程A從來不會計算最終結果。這個通常稱為死鎖。

  • 性能:iPhone應用最重要的一個目標就是有一個比較好的性能和更靈敏的UI。因此,你的性能目標必須達到。活躍性只關注一些最終發生的事情;它并不關心多快獲取到結果。


我將會在接下來的部分使用例子來涉及到每一個標準,這樣你就可以理解什么樣會導致一個不好的結果,你如何解決它,使得你的應用運行時有一個比較高的性能。


安全性

安全性要求程序運行在多線程環境中,產生一個正確的期待的結果,就想他運行在單線程環境中一樣。我會討論一個潛在的在多線程環境中經常會發生的一個問題,當兩個或多個線程同時訪問相同的數據。


圖 6-5 描述了兩個線程如何返回一個相同的item而導致應用崩潰。在圖6-5中,線程1嘗試把item push到當前棧中。然后,線程2和線程3想要把item取出來,然后檢查確保這個item在這個棧中。但是,在兩個線程檢查之后,線程2先運行,然后獲取item。Oops!像你看到的,線程3已經沒有item可以獲取了。這會導致你的應用崩潰。


iOS使用多線程提高數據并發訪問 之六

你可以從ThreadSafety工程中獲取到樣例代碼,但是Listing 6-6 顯示了這個問題的代碼注解。注意這個問題不會總是出現,但是如果你運行足夠多的時間,它還是會發生的。代碼使用了NSMutableArray變量存儲,因此客戶端代碼能夠添加和刪除數據。


iOS使用多線程提高數據并發訪問 之六

iOS使用多線程提高數據并發訪問 之六


當你運行上面的代碼一段時間,你會收到下面的信息:

iOS使用多線程提高數據并發訪問 之六

它告訴你,你嘗試在一個空的數組中刪除對象,這是不應該發生的當你在刪除之前已經檢查了數組空的情況。你甚至打印出來看它是否是最后一個對象。


現在,如果你再一次查看圖6-4,你應該理解為什么會崩潰 -- 因為第一個現場檢查和打印出最后一個對象后,第一個線程已經停止,而第二個線程還在運行。


解決辦法


對于這個問題我的解決辦法是鎖住這個方法直到線程執行完。鎖是一種機制,它能夠確保在一個時間內只有一個線程訪問一個指定的代碼塊。想象一下,你現在在一個比賽中,需要直接和很多人競爭。你和你的競爭者被問了一個問題,而誰先響鈴誰就能先回答問題。在第一個結束之后,另外一個人又可以搖鈴了。當第一個人在回答問題時,這個鈴是被鎖住的。線程也是一樣的。你可以創建一個鎖,就像是你的鈴一樣:第一個得到鎖的線程(類似搖鈴)會阻塞其他所有的線程直到它結束。在第一個線程結束之后,鎖就開了(類似于其他人可以搖鈴了);其他線程能嘗試獲取鎖,而這個過程可以重復下去。


鎖機制的基本概念就是確保當一個線程在執行任務時,其他線程不能打斷。例如,如果線程1獲取到這個對象,然后打印出來,線程2必須等到線程1執行完才能獲取和從數組中刪除對象。


這個鎖創建在一個對象上。如果線程1從對象A獲取了鎖,其他線程就不能再獲取這個對象的鎖了,這些線程必須等待線程1執行完后,然后把鎖返回給對象A。


最簡單的方式獲取對象A的鎖的就是使用@synchronized(objA),如下面Listing 6-7 的代碼。


iOS使用多線程提高數據并發訪問 之六

iOS使用多線程提高數據并發訪問 之六


注意:在很多情況下,使用self作為鎖,效果是一樣的。你只需要確保你想要鎖住的對象使用同一個對象鎖即可。例如,你有兩個存儲變量,你可以考慮為每一個單獨是有關一個鎖。



圖6-6 顯示了@synchronized在線程中是如何工作的。


iOS使用多線程提高數據并發訪問 之六

你需要同時同步push和pop data這兩個方法,因為如果你只鎖住其中的一個方法,當你pop檢查時,依然會存在風險,還有存儲器push了很多數據,而你不沒有按照你想要的方式獲取到對象。為了防止這些,你需要使用lockObj同時鎖住他們,這樣在一個時間段就只有一個方法在運行。


你的代碼是安全的,但是依然還有兩個更重要的多線程屬性需要討論。



向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

武鸣县| 定远县| 襄汾县| 扎兰屯市| 达拉特旗| 中江县| 兖州市| 宝丰县| 都江堰市| 黑河市| 蓝田县| 肥东县| 洛浦县| 浮梁县| 德江县| 喀喇| 黑河市| 岱山县| 吴川市| 毕节市| 宜宾县| 海原县| 岐山县| 福贡县| 田东县| 广德县| 巴彦淖尔市| 庆城县| 武隆县| 通榆县| 嵊州市| 达尔| 永定县| 贵德县| 万年县| 赞皇县| 宁陵县| 阳城县| 来凤县| 柏乡县| 海林市|