GCD多線程同步實現(xiàn)鎖效果

多線程同步?這個有什么意義呢。
多線程編程里面,一些敏感數(shù)據(jù)不允許被多個線程同時訪問,此時就使用同步訪問技術,保證數(shù)據(jù)在任何時刻,最多有一個線程訪問,以保證數(shù)據(jù)的完整性。
先來個概念性的東西,理解下

信號量

信號量(Semaphore),有時被稱為信號燈,是在多線程環(huán)境下使用的一種設施,是可以用來保證兩個或多個關鍵代碼段不被并發(fā)調(diào)用。在進入一個關鍵代碼段之前,線程必須獲取一個信號量;一旦該關鍵代碼段完成了,那么該線程必須釋放信號量。其它想進入該關鍵代碼段的線程必須等待直到第一個線程釋放信號量。為了完成這個過程,需要創(chuàng)建一個信號量VI,然后將Acquire Semaphore VI以及Release Semaphore VI分別放置在每個關鍵代碼段的首末端。確認這些信號量VI引用的是初始創(chuàng)建的信號量。

可以簡單理解成線程同步作用和加鎖相似。其實同步和加鎖是有區(qū)別的。只是線程同步的效果和加鎖之后的作用一樣。具體下一篇會有解釋。不廢話了,直奔代碼

先模擬用戶去買票,一共提供三條通道,買票。

沒有進行線程同步
線程沒有同步

上述是開啟三條線程,然后都是同時去對數(shù)據(jù)進行減減操作。會發(fā)現(xiàn),數(shù)據(jù)出現(xiàn)異常。那是因為,多條線程同時訪問這個數(shù)據(jù)時候,該線程只是讀取到他訪問時候的數(shù)據(jù),若此時還有其他線程對該數(shù)據(jù)進行操作的話。則這個數(shù)據(jù)就會出現(xiàn)異常。

一:GCD中的信號量實現(xiàn)線程同步
- (void)viewDidLoad {
    [super viewDidLoad];
   
    // 實例類person
    self.person = [[Person alloc] init];
    self.person.num = 100;
    
    
    //dispatch_semaphore_create(1) 創(chuàng)建一個信號量,設置信號量的資源數(shù)0表示沒有資源,調(diào)用dispatch_semaphore_wait會立即等待。
    //dispatch_semaphore_signal  發(fā)送一個信號會讓信號量+1
    //dispatch_semaphore_wait  等待信號會讓信號量 —1
    self.semaphore = dispatch_semaphore_create(1);
    
    //模擬三條不同的網(wǎng)絡去搶票
    [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timeActionA) userInfo:nil repeats:YES];
    [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(timeActionB) userInfo:nil repeats:YES];
    [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timeActionC) userInfo:nil repeats:YES];
    
}

- (void)timeActionA{
       // 線程A
 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //等待信號,當信號總量少于0的時候就會一直等待,否則就可以正常的執(zhí)行,并讓信號總量-1
        dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
        [self.person personA];
        //發(fā)送一個信號,自然會讓信號總量加1,
        dispatch_semaphore_signal(self.semaphore); 
    });   
}
- (void)timeActionB{    
    // 線程A
 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
        [self.person personB];
        dispatch_semaphore_signal(self.semaphore);
    });   
}
- (void)timeActionC{   
    // 線程A
 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
        [self.person personC];
        dispatch_semaphore_signal(self.semaphore);
    });
}

Person類的實現(xiàn)。

-(void)personA{
    self.num--;
    NSLog(@"A票通道  剩余總票:%ld",(long)self.num);}
-(void)personB{
    self.num--;
    NSLog(@"B票通道  剩余總票:%ld",(long)self.num);
}

-(void)personC{
    self.num--;
    NSLog(@"C票通道  剩余總票:%ld",(long)self.num);   
}
模擬搶票Log
一:GCD分組實現(xiàn)線程同步
- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 實例類person
    self.person = [[Person alloc] init];
    self.person.num = 100;
    
    //創(chuàng)建隊列組隊
    self.group = dispatch_group_create();
    
    
    //模擬三條不同的網(wǎng)絡去搶票
    [NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(timeActionA) userInfo:nil repeats:YES];
    [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(timeActionB) userInfo:nil repeats:YES];
    [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(timeActionC) userInfo:nil repeats:YES];

    
}

- (void)timeActionA{
    
    //進入組
    dispatch_group_enter(self.group);
    //線程放進隊列組
    dispatch_group_async(self.group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self.person personA];
        //離開組
        dispatch_group_leave(self.group);
    });
}

- (void)timeActionB{    

    //進入組
    dispatch_group_enter(self.group);
    
    dispatch_group_async(self.group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        
        [self.person personB];
        dispatch_group_leave(self.group);
        
    });

}

- (void)timeActionC{
    //進入組
    dispatch_group_enter(self.group);
    
    dispatch_group_async(self.group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        
        [self.person personC];
        dispatch_group_leave(self.group); 
    });
}
線程組模擬線程同步
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容