iOS多線程-線程同步/線程安全

同步任務線程同步是兩個概念溯捆。不要搞混了。一定要區(qū)分當前線程所在線程的關系勾缭。

同步任務:串行執(zhí)行任務,會把你的同步代碼一行一行的執(zhí)行下去目养,即使是在block里面俩由,也會等待任務完成,會阻塞當前線程癌蚁。
異步任務:并行執(zhí)行的任務幻梯,代碼會放在另外一塊區(qū)域去執(zhí)行兜畸,不會會阻塞當前線程,不會等待執(zhí)行完畢返回結果碘梢。
異步線程:并行執(zhí)行的任務的線程咬摇。
線程同步:是指多個線程同時訪問一個資源時可能存在競爭問題提供的解決方案,使多個線程可以對同一個資源進行操作,比如線程A為數(shù)組M添加了一個數(shù)據(jù)煞躬,線程B可以接收到添加數(shù)據(jù)后的數(shù)組M肛鹏。線程同步就是線程之間相互的通信。

常見比如多個線程內操作了同一個變量恩沛,這個時候一定要考慮線程安全和同步在扰。

- (void)removeLastIamgeName{//假如每個進來的都是不同的線程
    //self.imageNames是NSMutableArray
    if (self.imageNames.count>0) {
        //比如當前count為1,那么第一個線程和第二個線程都可以進入判斷內部雷客,第一個線程刪除了數(shù)組里面最后一個數(shù)據(jù)健田,第二個線程去刪除的時候因為已經沒有數(shù)據(jù)了,count=0佛纫,這個時候取調用removeObjectAtIndex:0機會crash妓局,數(shù)組越界了
        [self.imageNames removeObjectAtIndex:self.imageNames.count-1];
    }
}

同步異步任務

這里有個概念容易混攪:
使用GCD創(chuàng)建一個并行隊列,如果向并行隊列添加同步任務呈宇,它并不是串行執(zhí)行的好爬。任務對于當前線程是同步串行執(zhí)行的,對于隊列來說是并行執(zhí)行的甥啄,只是隊列里面可能每次都只有一個任務存炮,所以看起來是串行的。
GCD的隊列定義了隊列里面的任務是否支持并行蜈漓,并沒有定義任務在當前線程是同步還是異步穆桂。

    dispatch_queue_t globalQueue = dispatch_queue_create([@"com.yasin.dispatchqueue" cStringUsingEncoding:NSASCIIStringEncoding], DISPATCH_QUEUE_CONCURRENT);;
    for (int i=0; i<10; i++) {
        dispatch_sync(globalQueue, ^(){
            NSLog(@"%d",i);
             /**
                 *  i從0到9輸出,因為當前線程是串行的融虽,會等待同步任務執(zhí)行完畢
                 如果在for循環(huán)內部再起一個異步線程享完,在異步線程內執(zhí)行dispatch_sync(globalQueue, ^(),輸出就是亂序的
                 */
        });
    }

這里會一個接著一個執(zhí)行同步線程的任務有额,并不會出現(xiàn)幾個線程同時執(zhí)行的現(xiàn)象般又。當前線程規(guī)定了要同步一個一個執(zhí)行線程任務怎么可能會并行執(zhí)行多個任務。這個代碼書寫邏輯就不對巍佑。

--小結-- 其實只要不做傻事就不會出問題茴迁,要一個一個執(zhí)行的任務就放在串行隊列里面,需要異步就異步萤衰,需要同步就同步(異步不卡當前線程堕义,同步卡當前線程);如果想要并行執(zhí)行多個任務脆栋,就放在并行隊列里面倦卖,開異步線程去做洒擦。

線程同步的方法

  • 原子操作
    我們在聲明一個變量的時候一般會使用nonatomic,這個就是非原子操作糖耸;原子操作是atomic秘遏。
    簡單的加減使用原子操作具有更高的性能優(yōu)勢。注意是加減嘉竟,不是增刪0钗!!
    也就是說僅僅對于getter,setter是線程安全的舍扰,兩個線程都去對變量賦值是安全的倦蚪。對于比如NSMutableArray類型的增刪操作不是線程安全的

  • 線程鎖
    鎖可以保護臨界區(qū),代碼在臨界區(qū)同一時間只會被一個線程執(zhí)行边苹。有互斥鎖陵且、遞歸鎖、讀寫鎖个束、分布鎖慕购、自旋鎖、雙重檢查鎖等等茬底。
    后續(xù)會重點介紹這部分

  • 條件沪悲、信號量
    有個BOOL類型的變量,當線程A進入臨界區(qū)時把BOOL值置為NO阱表,如果線程B準備進入臨界區(qū)時發(fā)現(xiàn)BOOL值為NO就掛起等待殿如,當線程A出臨界區(qū)時把BOOL置為YES,線程B會被喚醒并繼續(xù)執(zhí)行最爬。
    條件就是使用信號量在線程之間相互發(fā)生信號涉馁。
    條件通常被使用來說明資源可用性,或用來確保任務以特定的順序執(zhí)行爱致。

  • 使用Selector
    selector方法允許你的線程以異步的方式來傳遞消息烤送,以確保它們在同一個線程上面執(zhí)行是同步的。
    比如NSObject中的方法

performSelector:withObject:afterDelay:
performSelectorInBackground:withObject:
performSelector:onThread:withObject:waitUntilDone:

代碼:

[self performSelector:@selector(test:) withObject:nil afterDelay:1];
[self performSelectorInBackground:@selector(test:) withObject:nil];
//等效于[NSThread detachNewThreadSelector:@selector(test:) toTarget:self withObject:nil];

代碼2:

-(void)viewDidLoad
{
    [super viewDidLoad];
    
    [self threadInfo:@"UI"];
    
    _isNewThreadAborted = NO;
    _thread = [[NSThread alloc] initWithTarget:self selector:@selector(newThread:) object:nil];
    //開始線程
    [_thread start];
    //在另一個線程中的Run Loop中執(zhí)行Selector
    [self performSelector:@selector(test:) onThread:_thread withObject:nil waitUntilDone:NO];
}
//在新線程中創(chuàng)建并開始一個NSRunLoop
-(void)newThread:(id)obj
{
    @autoreleasepool
    {
        NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop];
        while (!_isNewThreadAborted)
        {
            [currentRunLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
        }
        NSLog(@"線程停止");
    }
}
//Selector執(zhí)行
-(void)test:(id)obj
{
    [self threadInfo:@"test"];
    _isNewThreadAborted = YES;
}
-(void)threadInfo:(NSString*)category
{
    NSLog(@"%@ - %@", category, [NSThread currentThread]);
}
  • 內存屏障和 Volatile 變量
    OSMemoryBarrier函數(shù)蒜鸡,設置內存屏蔽
    volatile變量
    因為內存屏障和volatile變量降低了編譯器可執(zhí)行的優(yōu)化胯努,因此你應該謹慎使用它們,只在有需要的地方時候逢防,以確保正確性。
    這部分涉及編譯器蒲讯,現(xiàn)在還不是很理解忘朝,以后再補充

并行并發(fā)

并發(fā)編程、并發(fā)程序判帮,和并行計算機局嘁。
并發(fā)性與軟件結構有關溉箕,而并行性與硬件有關。
也就是說悦昵,并發(fā)就是多線程編程肴茄,并行就是多核處理器。

天下武功出少林

這里推薦一個特別好的文章iOS多線程編程指南(四)線程同步

后續(xù)我會著重研究線程鎖這一塊

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末但指,一起剝皮案震驚了整個濱河市寡痰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌棋凳,老刑警劉巖拦坠,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異剩岳,居然都是意外死亡贞滨,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進店門拍棕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來晓铆,“玉大人,你說我怎么就攤上這事绰播〗驹耄” “怎么了?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵幅垮,是天一觀的道長腰池。 經常有香客問我,道長忙芒,這世上最難降的妖魔是什么船万? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任擦秽,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘纳猪。我一直安慰自己,他們只是感情好或舞,可當我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布哗魂。 她就那樣靜靜地躺著,像睡著了一般忱嘹。 火紅的嫁衣襯著肌膚如雪嘱腥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天拘悦,我揣著相機與錄音齿兔,去河邊找鬼。 笑死,一個胖子當著我的面吹牛分苇,可吹牛的內容都是我干的添诉。 我是一名探鬼主播,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼医寿,長吁一口氣:“原來是場噩夢啊……” “哼栏赴!你這毒婦竟也來了?” 一聲冷哼從身側響起靖秩,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤须眷,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后盆偿,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體柒爸,經...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年事扭,在試婚紗的時候發(fā)現(xiàn)自己被綠了捎稚。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡求橄,死狀恐怖今野,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情罐农,我是刑警寧澤条霜,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站涵亏,受9級特大地震影響宰睡,放射性物質發(fā)生泄漏。R本人自食惡果不足惜气筋,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一拆内、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧宠默,春花似錦麸恍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至瓤球,卻和暖如春融欧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背卦羡。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工蹬癌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留权她,地道東北人虹茶。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓逝薪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蝴罪。 傳聞我的和親對象是個殘疾皇子董济,可洞房花燭夜當晚...
    茶點故事閱讀 43,509評論 2 348

推薦閱讀更多精彩內容