色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

線程同步技術介紹

科技綠洲 ? 來源:Linux開發架構之路 ? 作者:Linux開發架構之路 ? 2023-11-13 14:19 ? 次閱讀

正文:首先看一下問題引出,先看一些經典的問題.

多線程的隱患

首先我們利用多線程的話肯定是好處多多,因為我們可以同時去做一些事情,大大的提高了效率.像我們下載視頻的時候就可以同時下載多個視頻,這樣是節省了很多時間,用戶體驗也會更好.但是用得時候也會存在一些安全隱患,比如同一塊資源可能會被多個線程共享,也就是多個線程可能會訪問同一塊資源,這樣會出現一些數據錯亂和數據安全的問題.下面我們就看一些例子.

存錢取錢案例

比如我現在有1000元,同時有2個線程去處理,一個線程是取錢100元,一個線程是存錢100元,我制作了一張示意圖如下:

圖片

存錢取錢示意圖

我們從上面的圖應該很清楚,存100、取100的最終結果就是還是剩余1000元,但是看我們上面的示意圖,最終結果要么是900要么是1100,這就與1000的結果對不上,所以很明顯用多線程是會存在隱患,下面我們用代碼演示一下上面的結果:

圖片

賣票案例

這個和上面的稍微有點差別,因為上面的是2個操作,而賣票呢,它是1個操作.同樣的比如我現在有1000張票,同時有2個線程去處理賣票,一個線程是一個線程賣票100張,另一個線程也是賣票100張,同時操作的話,也會出現異常,我制作了一張示意圖如下:

圖片

我們同樣的也可以用代碼演示一下效果:

圖片

上面的兩個,大家可以試試.接下來針對上面的問題,我們就引出了今天的主角,線程同步技術

線程同步技術

解決方案:使用線程同步技術 (同步,就是協同步調,按照預定的先后次序進行運行),我們先來看下線程同步技術有哪些方案:線程同步方案最常見的技術就是:加鎖.大概方案如下(大致這么多方案,當然還有其他的)

OSSpinLock (自旋鎖)

os_unfair_lock (互斥鎖)

pthread_mutex (互斥鎖、遞歸鎖)(里面3種類型,目前只說2種對我們有用的)

dispatch_queue (DISPATCH_QUEUE_SERIAL)

NSLock

NSRecursiveLock

NSCondition

NSConditionLock

@synchronized

以上的這些都是可以做到線程同步方案,我會一個一個介紹,并且介紹它們的優缺點,性能怎么樣,我們怎么去選擇等等.我們就以上面的例子講解.

OSSpinLock (自旋鎖)

OSSpinLock 叫做 "自旋鎖", 等待鎖的狀態會處于忙等( busy-wait )狀態,一直占用著CPU內存.頭文件導入,而且這個鎖是過期鎖,iOS10以后就過期了,但是我們還是來看看,因為面試中可能會遇到,用法如下:

初始化鎖:OSSpinLock spinLock = OS_SPINLOCK_INIT;

加鎖: OSSpinLockLock(&_spinLock);

解鎖: OSSpinLockUnlock(&_spinLock);

我們先看賣票:

圖片

我是加鎖和解鎖了,為什么上面的代碼還有問題,有發現原因的嗎?這是因為SpinLock是局部變量,所以我們進去都是初始化了一把新鎖,這把鎖并沒有被使用過,是達不到加鎖的目的.所以所有的線程都是用同一把鎖才能達到加鎖的目的.請看下面代碼:

圖片

確實是剩下85張,沒有問題.原理是這樣,每次執行saleTicket都會進入 //加鎖: OSSpinLockLock(&_SpinLock) 這個代碼,第一次進來是正常給_SpinLock加鎖,第二次進來的時候,發現_SpinLock已經被人加了鎖,它會在這邊等待,等待這把鎖被解鎖,解鎖完了以后然后它再去加鎖,就這樣依次進行,就保證了里面的那段代碼同時只有一個線程在處理.這就解決了線程同步的問題.

接下來我們就看存錢和取錢的問題.存錢、取錢是2個操作,我們是用同一把鎖還是2把鎖?思考了這個問題我們就知道怎么做了,因為存錢和取錢是不能同時進行,所以我們就用同一把鎖即可(2把鎖是有問題的大家可以自己試試),請看下面的代碼,我們驗證一下:

圖片

自旋鎖"忙等"狀態是怎么等呢?忙等就是一直忙碌,而且還在等待,類似這樣while(鎖還沒有解開),就會一直執行,占用cpu,直到鎖被放開.而且OSSpinLock是已經過期了,而且目前已經不再安全,可能會出現優先級反轉的問題.

下面說一下線程的調度問題

圖片

其實你看上面的圖,如果隨著時間的推移,操作系統把時間給thread1一點時間,再給thread2一點時間,再給thread3一點時間,而且這個時間周期非常短,就這樣一直非??斓那袚Q,這樣下來給我們的感覺就是同時執行.這就是實現多線程的一個方案.也就是多線程的原理,我們也可以說這是時間片輪轉調度算法.調用進程或者線程都是用這套算法

還有個就是線程的優先級問題,比如thread1的優先級比較高,那么操作系統就會給thread1多一點時間去執行.其他的線程就少一點時間去執行.這樣的話,我們使用自旋鎖就會存在一個優先級反轉的問題.比如thread1優先級非常高,thread2優先級很低.首先是thread2先進去加鎖,thread1再進來就會等thread2解鎖,由于thread1的優先級非常高,CPU就把大量的時間給了thread1,此時可能導致thread2沒有時間執行解鎖,thread1就會一直執行等待,有點死鎖的感覺.

這樣大家想一想:如果優先級高的不是忙等,而是休眠,休息就不會占用CPU,那不就是解決了這個問題.

os_unfair_lock (互斥鎖)

os_unfair_lock用于取代不安全OSSpinLock,是從iOS10開始支持.

從底層調用看,等待os_unfair_lock鎖的線程會處于休眠狀態,并非忙等(后面會證明一下)

它的用法和OSSpinLock非常像,需要倒入頭文件,用法如下:

初始化鎖:os_unfair_lock unfairLock = OS_UNFAIR_LOCK_INIT;

加鎖: os_unfair_lock_lock(&_unfairLock);

解鎖:os_unfair_lock_unlock(&_unfairLock);

下面我們就去看一下用法

圖片

存錢和取錢也是一樣的道理,我們可以自己試試.

pthread_mutex (互斥鎖)

像這種pthread開頭的一般都是跨平臺的Windows、linux等等都是可以用的,mutex叫做"互斥鎖",等待鎖的線程會處于休眠狀態

其實用法都是差不多,我們先來看下怎么用,這個稍微代碼多一點點

//初始化屬性
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
    //初始化鎖
    pthread_mutex_init(&_mutex, &attr);(&attr也可以傳NULL,這樣的話,上面的都是默認的,上面可以都不用寫)
    //加鎖
    pthread_mutex_lock(&_mutex);
    //解鎖
    pthread_mutex_unlock(&_mutex);
    //銷毀相關資源
    pthread_mutexattr_destroy(&attr);
    pthread_mutex_destroy(&_mutex);

其中PTHREAD_MUTEX_NORMAL是鎖的類型,后面會細說,先傳默認PTHREAD_MUTEX_NORMAL

先看運行結果:

圖片

沒有問題,記得銷毀哈,之前說的2個鎖,沒有提供銷毀的方法,那我們就不寫,如果提供了,我們還是寫一下的好!

pthread_mutex (遞歸鎖)

我們再看另一種情況,請看下面的代碼:

圖片

上面這些代碼會出現什么情況?死鎖,會出現相互等待的情況,只會輸出第一個NSLog,遇到這種情況我們怎么解決才好呢?2把不同的鎖即可解決問題,就是otherMutexTest里面一把鎖,otherMutexTest2里面另一把鎖就可以解決了,這個我就不截圖了,我們可以自己試試

再看下面另一種情況:出現遞歸怎么辦?如下圖

圖片

遇到上面的這種情況我們又怎么處理,如果就像截圖那樣的話,就會出現休眠等待.如果我們想執行下去,我們就是可以設置鎖的類型來解決這個問題:一共3種類型如下

圖片

我們只要把鎖的類型換成遞歸鎖,立刻就能解決這個問題,我們加一個遞歸停止條件,不然會一直運行

圖片

還有一個注意的,這個允許重復加鎖,一定是在同一個線程,如果是多個線程的話,就不行.遞歸鎖:允許同一個線程對一把鎖重復加鎖.

自旋鎖、互斥鎖匯編分析

自旋鎖:一直忙等,占用CPU內存,一直在執行代碼;互斥鎖:不等待,休眠.不執行代碼.我們怎么去證明這個問題呢?我們可以從匯編實現上去證明這個問題,我們先看OSSpinLock自旋鎖:

圖片

首先我們如果用這個上面的來調試的話,是看不出來什么效果的,因為這里面都是一大段一大段匯編代碼執行的,我們需要一句一句的執行匯編指令.就需要敲si,s是step的意思,代碼一行一行的執行,如果只用s的話,就是一行oc代碼執行,一行oc對應可能一大段匯編,所以我們還需要加i,i是instruction的意思是一行一行匯編指令執行,簡稱si. 還有個是nexti,它也是一行一行匯編指令執行,只是nexti它是遇到函數就會一下執行過去.因為我們要看函數實現,所以我們用si.

我們再看一下,我代碼是怎么寫的:

圖片

我是創建了10個線程去執行賣票,而且在賣票中間sleep(100),這樣是為了,第一條線程進去,我們不管,我們主要看第二條線程在這等待的時間,到底做了什么事.所以我們主要看第二條的匯編代碼.sleep(100)是為了時間長點,方便我們能看出做什么事.如果時間太短,直接第二條線程就不等待,那我們就看不到效果,請看下面的結果

圖片

從上面的結果看,進入OSSpinLockLock函數,它會一直在81aef那里一直循環執行,這是外循環,我們所說的自旋鎖就是這樣,一直循環執行,占用CPU內存.一旦有人放開這把鎖就會條件循環結束,不會再執行循環.

接下來我們看看互斥鎖pthread_mutex

查找的方法和上面的一樣,我就截圖最關鍵的圖即可,請看下面:

圖片

執行到最后,直接是callsys,調用系統的方法,是不是類似我之前說的runloop里面的休眠的方法,而且我們知道休眠是任何事情都不會做,不占用CPU內存,所以我們最后看到,我的模擬器立刻又彈出來了,說明確實是睡眠,不占用任何CPU內存.

os_unfair_lock_lock我們可以用上面的方法嘗試,它的結果也是互斥鎖.

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 數據
    +關注

    關注

    8

    文章

    7134

    瀏覽量

    89443
  • 操作系統
    +關注

    關注

    37

    文章

    6889

    瀏覽量

    123627
  • 代碼
    +關注

    關注

    30

    文章

    4823

    瀏覽量

    68922
  • 多線程同步
    +關注

    關注

    0

    文章

    2

    瀏覽量

    5245
收藏 人收藏

    評論

    相關推薦

    一文詳解Linux線程同步

    我們在工作中會經常遇到線程同步,那么到底什么是線程同步呢,線程同步的本質是什么,
    發表于 08-25 11:49 ?645次閱讀

    線程編程之四 線程同步

    介紹最常用的四種:臨界區(CCriticalSection) 事件(CEvent) 互斥量(CMutex) 信號量(CSemaphore)  通過這些類,我們可以比較容易地做到線程同步。A
    發表于 10-22 11:43

    Linux多線程線程同步

    。同一進程內的線程共享進程的地址空間。通信:進程間通信IPC,線程間可以直接讀寫進程數據段(如全局變量)來進行通信——需要進程同步和互斥手段的輔助,以保證數據的一致性。調度和切換:線程
    發表于 12-08 14:14

    IOT-OS之RT-Thread--- 線程同步線程間通信

    rt_thread,下面要介紹線程間的同步與通信,線程同步對象rt_sem / rt_mutex / rt_event和
    發表于 07-02 06:15

    QNX環境下多線程編程

    介紹了QNX 實時操作系統和多線程編程技術,包括線程同步的方法、多線程程序的分析步驟、
    發表于 08-12 17:37 ?30次下載

    Linux多線程同步方法

    線程對共享相同內存操作時,就會出現多個線程對同一資源的使用,為此,需要對這些線程進行同步,以確保它們在訪問共享內存的時候不會訪問到無效的數值。
    發表于 08-08 14:17 ?2063次閱讀

    Win32多線程同步技術淺析

    簡要介紹了在Win32環境下多線程訪問共享資源時的同步機制,討論了主要的4種同步對象(臨界區、互斥元、事件、信號量),并描述了它們的優缺點,給出了使用Win32 API函數操控這4種對
    發表于 11-14 10:55 ?31次下載
    Win32多<b class='flag-5'>線程</b><b class='flag-5'>同步</b><b class='flag-5'>技術</b>淺析

    java多線程同步方法

    二、為什么要線程同步 因為當我們有多個線程要同時訪問一個變量或對象時,如果這些線程中既有讀又有寫操作時,就會導致變量值或對象的狀態出現混亂,從而導致程序異常。舉個例子,如果一個銀行賬戶
    發表于 09-27 13:19 ?0次下載

    C#多線程技術

    C#和.NET類庫為開發多線程應用程序提供了很方便的支持,本章首先簡要介紹.NET類庫中的Thread類及各種線程支持,再通過示例說明線程使用中需要掌握的規則,最后論述
    發表于 04-23 11:32 ?15次下載

    各型號的DSPBIOS線程同步原語以及相關的問題和約束

    DSP編程已經從單循環程序過渡到使用實時特征的復雜多線程應用程序。多線程應用程序需要同步對共享資源的訪問。 DSP/BIOS提供了同步線程
    發表于 05-03 09:24 ?4次下載
    各型號的DSPBIOS<b class='flag-5'>線程</b><b class='flag-5'>同步</b>原語以及相關的問題和約束

    了解Linux多線程線程同步

    進程間通信IPC,線程間可以直接讀寫進程數據段(如全局變量)來進行通信——需要進程同步和互斥手段的輔助,以保證數據的一致性。
    發表于 04-23 14:23 ?739次閱讀
    了解Linux多<b class='flag-5'>線程</b>及<b class='flag-5'>線程</b>間<b class='flag-5'>同步</b>

    使用C#實現Interlocked線程同步的程序免費下載

    本文檔的主要內容詳細介紹的是使用C#實現Interlocked線程同步的程序免費下載。
    發表于 07-21 08:00 ?1次下載
    使用C#實現Interlocked<b class='flag-5'>線程</b><b class='flag-5'>同步</b>的程序免費下載

    RT-Thread文檔_線程同步

    RT-Thread文檔_線程同步
    發表于 02-22 18:29 ?1次下載
    RT-Thread文檔_<b class='flag-5'>線程</b>間<b class='flag-5'>同步</b>

    線程同步的幾種方法

    線程同步是指在多個線程并發執行的情況下,為了保證線程執行的正確性和一致性,需要采用特定的方法來協調線程之間的執行順序和共享資源的訪問。下面
    的頭像 發表于 11-17 14:16 ?1241次閱讀

    線程如何保證數據的同步

    。本文將詳細介紹線程數據同步的概念、問題、以及常見的解決方案。 一、多線程數據同步概念 在多線程
    的頭像 發表于 11-17 14:22 ?1304次閱讀
    主站蜘蛛池模板: 日本久久免费大片 | 成人免费视频在线观看 | 肉欲横流(NP高H)| 亚洲精品第二页 | 一个人的免费高清影院 | 校花的奶好大好浪 | 色欲久久综合亚洲精品蜜桃 | 国产午夜精品鲁丝片 | 中国老太太xxx | 无码内射成人免费喷射 | 四虎视频最新视频在线观看 | 大学生高潮无套内谢视频 | 国产亚洲美女在线视频视频 | 日本精品在线观看视频 | 日韩精品一区二区亚洲AV观看 | 九色PORNY真实丨首页 | 欧美亚洲国产激情一区二区 | 中国国产不卡视频在线观看 | 男人天堂2018亚洲男人天堂 | 色欲天天婬色婬香影院 | 99久久蜜臀亚洲AV无码精品 | 暖暖视频免费观看视频 | 国产噜噜噜精品免费 | 午夜性爽视频男人的天堂在线 | 国产精品18久久久久久欧美 | 久久这里只有精品国产精品99 | 全彩acg无翼乌火影忍者 | 国产AV精品国语对白国产 | 差差差差差差差差免费观看 | 免费国产久久啪久久爱 | 99热在线视频 | 成人区精品一区二区不卡AV免费 | 欧美精品乱码99久久蜜桃 | 亚洲中文字幕一二三四区苍井空 | 国产1000部成人免费视频 | 露露的性战k8经典 | 日本VA在线视频播放 | 亚洲国产亚综合在线区尤物 | 久久影院毛片一区二区 | 国产综合自拍 偷拍在线 | 亚洲视频区 |