05-dispatch_semphore

葉喬木發表於2018-12-14

dispatch_semphore 訊號量

dispatch_semaphore訊號量為基於計數器的一種多執行緒同步機制。如果semaphore計數大於等於1,計數-1,返回,程式繼續執行。如果計數為0,則等待。dispatch_semaphore_signal(semaphore)為計數+1操作,dispatch_semaphore_wait(sema,
DISPATCH_TIME_FOREVER)為設定等待時間,這裡設定的等待

三個方法:

  • 1 建立訊號

    dispatch_semaphore_t sem = dispatch_semaphore_create(0);

  • 2 傳送一個訊號,讓訊號量進行+1操作
    dispatch_semaphore_signal(sem);

  • 3 是總訊號-1的操作,當訊號量為0的時候,會阻塞執行緒
    dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);

使用示例:

- (IBAction)loadDataBtnClick:(id)sender {
 	
	// 去下載圖片,等待所有的圖片下載完成 去進行展示
	// 因此就有了一個同步的概念
	NSArray *imgUrlArr = @[@"http://g.hiphotos.baidu.com/image/h%3D220/sign=25515a55865494ee9822081b1df4e0e1/c2fdfc039245d68802b0694eaec27d1ed31b24ae.jpg",@"http://h.hiphotos.baidu.com/image/pic/item/d4628535e5dde711e70b7e1dadefce1b9c16617b.jpg",@"http://g.hiphotos.baidu.com/image/pic/item/95eef01f3a292df54e6346fbb6315c6035a873b8.jpg"];
	
	// 建立一個 semaphore 基於計數器的一種多執行緒同步機制。
	dispatch_semaphore_t sem = dispatch_semaphore_create(0);
	//
	
	
	for (int i = 0; i < imgUrlArr.count; i ++) {
	

		// 執行任務一 操作
			NSURL *url = [NSURL URLWithString:imgUrlArr[i]];
			NSURLRequest *req = [NSURLRequest requestWithURL:url];
		
			NSURLSessionDataTask *task = [self.session dataTaskWithRequest:req completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
				if (!error) {
					// 沒有錯誤 請求成功
					UIImage *image = [UIImage imageWithData:data];
					[_succImgArr addObject:image];
					NSLog(@"download %d img success",i);
				}else{
					NSLog(@"error happend");
				}
				
				// 當最後一次回撥 後再發訊號量,使程式繼續執行
				if (i == 2) {
					// 計數加一的操作
    				dispatch_semaphore_signal(sem);
					
					NSLog(@"%lu",(unsigned long)self.succImgArr.count);
				}
				
				
			}];
		
			[task resume];
		
		
	}
	
	// 等待完成 訊號量不為0 程式繼續執行
	dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
	
	dispatch_async(dispatch_get_main_queue(), ^{
	
		NSLog(@"end");
		_firstShowImgView.image = self.succImgArr[0];
		_secondShowImgView.image = self.succImgArr[1];
		_thirdShowImgview.image = self.succImgArr[2];
		NSLog(@"%lu",(unsigned long)self.succImgArr.count);

    });
	

	
	/*
	
	輸出結果:
2017-12-08 10:16:00.605357+0800 SKNetDemo[32281:6366178] download 0 img success
2017-12-08 10:16:00.607327+0800 SKNetDemo[32281:6366178] download 1 img success
2017-12-08 10:16:00.608976+0800 SKNetDemo[32281:6366178] download 2 img success
2017-12-08 10:16:00.609852+0800 SKNetDemo[32281:6366178] 3
2017-12-08 10:16:00.611645+0800 SKNetDemo[32281:6366139] end
2017-12-08 10:16:00.612564+0800 SKNetDemo[32281:6366139] 3


	*/

}