iOS-GCD 멀티스레드 Lock 사례
- (void)deadLockCase1 {
NSLog(@"1"); // 1
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"2"); // 2
});
NSLog(@"3"); // 3
}
:1 , 。
4
:
컨트롤러 출력에서 알 수 있듯이 퀘스트 2와 퀘스트 3이 실행되지 않았습니다. 이때 이미 잠겼습니다.디스패치 때문에...sync는 동기화되어 있으며, 그 자체가 현재 라인을 막습니다. 이 때 주 라인을 막습니다.현재 Block은 주 라인이 실행되기를 기다리고 있어 주 라인이 주 라인을 기다리고 자신이 자신을 기다리는 상황을 형성하여 사라진 자물쇠를 형성했다 :
1、비동기 디스패치async 실행
NSLog(@"1"); // 1
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"2"); // 2
});
NSLog(@"3"); // 3
:1 3 2
2. 주 스레드에서 운행하지 않고 하위 스레드에 놓는다
NSLog(@"1"); // 1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSLog(@"2"); // 2
});
NSLog(@"3"); // 3
:1 2 3
참고: Block에서 UI 새로 고침 작업이 있으면 하위 스레드에서 실행할 수 없습니다.crash
2. 사라진 장면2: (직렬 대기열 동기화 자신을 끼워넣기)
- (void)deadLockCase2 {
dispatch_queue_t aSerialDispatchQueue = dispatch_queue_create("com.test.deadlock.queue", DISPATCH_QUEUE_SERIAL);
NSLog(@"1"); // 1
dispatch_sync(aSerialDispatchQueue, ^{
NSLog(@"2"); // 2
dispatch_sync(aSerialDispatchQueue, ^{
NSLog(@"3"); // 3
});
NSLog(@"4"); // 4
});
NSLog(@"5"); // 5
}
:1 2 , 2 。
4
:
콘솔 출력 결과를 보면 퀘스트 2를 실행한 후 잠금이 꺼졌습니다.이 예에서 두 GCD가 모두 사용하는 동기화 방식이고 같은 직렬 대기열이기 때문에 이전의 예와 같이 자신이 자신을 기다리는 상황이 발생하여 사라진 자물쇠가 형성되었다 :
1. 두 번째 GCD를 비동기식으로 변경
- (void)deadLockCase2 {
dispatch_queue_t aSerialDispatchQueue = dispatch_queue_create("com.test.deadlock.queue", DISPATCH_QUEUE_SERIAL);
NSLog(@"1"); // 1
dispatch_sync(aSerialDispatchQueue, ^{
NSLog(@"2"); // 2
dispatch_async(aSerialDispatchQueue, ^{
NSLog(@"3"); // 3
});
NSLog(@"4"); // 4
});
NSLog(@"5"); // 5
}
:1 2 4 5 3
그러나 첫 번째 GCD를 비동기식으로 변경하면 문제가 해결되지 않습니다.
- (void)deadLockCase2 {
dispatch_queue_t aSerialDispatchQueue = dispatch_queue_create("com.test.deadlock.queue", DISPATCH_QUEUE_SERIAL);
NSLog(@"1"); // 1
dispatch_async(aSerialDispatchQueue, ^{
NSLog(@"2"); // 2
dispatch_sync(aSerialDispatchQueue, ^{
NSLog(@"3"); // 3
});
NSLog(@"4"); // 4
});
NSLog(@"5"); // 5
}
:
1
5
2
4
:
첫 번째 GCD는 비동기적이지만 두 번째 GCD는 동기화되고 두 번째 GCD는 첫 번째 GCD가 끝나기를 기다리고 첫 번째 GCD의 Block은 첫 번째 GCD가 끝나기를 기다리기 때문에 사라진 자물쇠가 형성된다.주: 상기에서 두 번째 GCD를 비동기적으로 바꾸고 첫 번째 GCD가 동기화되는 장면에 대해 자물쇠가 사라지지 않습니다. 두 번째 GCD가 비동기이기 때문에 첫 번째 GCD가 실행될 때까지 기다릴 필요가 없습니다. 이것은 첫 번째 GCD와 동기화 관계가 없습니다.이것은 첫 번째 GCD가 실행되는 동시에 자신의 Block을 실행하는 코드입니다.2. 두 GCD 모두 비동기식으로 변경
- (void)deadLockCase2 {
dispatch_queue_t aSerialDispatchQueue = dispatch_queue_create("com.test.deadlock.queue", DISPATCH_QUEUE_SERIAL);
NSLog(@"1"); // 1
dispatch_async(aSerialDispatchQueue, ^{
NSLog(@"2"); // 2
dispatch_async(aSerialDispatchQueue, ^{
NSLog(@"3"); // 3
});
NSLog(@"4"); // 4
});
NSLog(@"5"); // 5
}
:
1
5
2
4
3
3. 서로 다른 직렬 대기열을 사용
- (void)deadLockCase2 {
dispatch_queue_t aSerialDispatchQueue1 = dispatch_queue_create("com.test.deadlock.queue1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t aSerialDispatchQueue2 = dispatch_queue_create("com.test.deadlock.queue2", DISPATCH_QUEUE_SERIAL);
NSLog(@"1"); // 1
dispatch_sync(aSerialDispatchQueue1, ^{
NSLog(@"2"); // 2
dispatch_sync(aSerialDispatchQueue2, ^{
NSLog(@"3"); // 3
});
NSLog(@"4"); // 4
});
NSLog(@"5"); // 5
}
:
1
2
3
4
5
3. 사쇄 장면: 신호량 막힘 주선정
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
NSLog(@"semaphore create!");
dispatch_async(dispatch_get_main_queue(), ^{
dispatch_semaphore_signal(semaphore);
NSLog(@"semaphore plus 1");
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"semaphore minus 1");
}
4
:
현재 실행 중인 라인이 주 라인이면 상기 코드에 자물쇠가 사라집니다.디스패치 때문에...semaphore_wait(semaphore, DISPATCH TIME FOREVER)는 현재 스레드를 차단하고 대기 시간은 DISPATCHTIME_FOREVER - 영원히 기다리세요. 그러면 현재 라인인 메인 라인을 영원히 막을 수 있습니다.메인 라인의 디스패치semaphore_signal(semaphore)이 실행되지 않고 dispatchsemaphore_wait는 디스패치를 기다리고 있습니다semaphore_signal이 신호량을 바꾸면 사라진 자물쇠가 형성됩니다 :
전역 스케줄링 대기열과 같은 신호량을 병렬 대기열로 옮겨야 한다.다음 장면은 직렬 대기열로 이동해도 됩니다.그러나 직렬 대기열은 잠길 수 있습니다. (dispatch semaphore signal 방법을 실행해도 직렬 대기열에 대응하는 경우, 즉 앞서 언급한 직렬 대기열이 직렬 대기열을 끼워 넣는 장면입니다.)- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
NSLog(@"semaphore create!");
dispatch_async(dispatch_get_main_queue(), ^{
dispatch_semaphore_signal(semaphore);
NSLog(@"semaphore plus 1");
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"semaphore minus 1");
});
}
다음 코드의 운행 결과는 어떻습니까?
-(void)viewDidLoad {
[super viewDidLoad];
NSLog(@"1");
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"2");
});
NSLog(@"3");
}
출력만: 1.뒤에 붕괴되었습니다. (dispatch get main queue (),^ {...}.너를 기다리게 하고 내가 너를 기다리게 하고 결국은 자물쇠가 사라지게 할 것이다.
참고 자료
4. 다음 코드 인쇄 순서는?
//dispatchqueue_create 함수로 생성된 concurrent Dispatch Queue 대기열과 함께 dispatch 사용queue_t queue = dispatch_queue_create("test_queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"----1-----%@", [NSThread currentThread]);
});
dispatch_barrier_async(queue, ^{// barrier
NSLog(@"----2----barrier-----%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----3-----%@", [NSThread currentThread]);
});
1、2、3
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.