2013-09-04 4 views
10

블록 내에서 dispatch_async()를 호출 할 때 @synchronized()를 사용하여 IOS에서 잠금이 어떻게됩니까? 예를 들어동기화 된 블록 및 dispatch_async

:

id myID 
-(void) foobar 
{ 
    @synchronized(myID){ 
     dispatch_async(){ //do stuff with myID}; 
    } 
} 

잠금은 dispatch_async 호출 내에서 유효한 아직인가? 또는 더 중요한 것은 dispatch_async() 내에서 또 다른 @synchronized() 호출을 사용할 때 단점이 있습니까?

+0

달성하려는 목표는 무엇입니까? – Wain

+0

BTW, 나는 당신이 _mot_ 어떤 시점에서 'myID'를 reinstantiating 있다고 가정하여 맞습니까? '@ synchronized' 블록은 일반적으로 변수가 아니라 myID가 가리키는 객체의 특정 인스턴스에 고유합니다. – Rob

답변

3

자물쇠를 사용하면 두 개의 다른 블록이 한 번에 발송되지 않습니다. 그러나 그것들은 비동기 적으로 보내 지므로 수행 될 수도 있고 미래에 임의로 수행 될 수도 있습니다. 디스패치 호출도 완료 될 때까지 기다리지 않습니다.

따라서 블록 내부의 내용은 동기화되지 않습니다. 최소한의 변경으로이를 달성하기위한 옵션은 동기 디스패치 또는 블록 내에서의 동기화뿐입니다.

무엇을하고 있느냐에 따라 가장 좋은 아이디어는 직렬 디스패치 대기열을 설정하고 블록을 디스패치하는 것입니다.

8

백그라운드 대기열에서이 myID 개체와의 상호 작용을 동기화하려는 경우, 다른 방법으로는 전달 된 블록 내부의 잠금을 원할 것입니다. 지금 당신은 : 당신의 큐에 파견 블록을 추가하는 과정을 동기화하지만,하지있어

@synchronized(myID) { 
    dispatch_async(queue, ^{ 
     // do stuff with myID 
    }); 
} 

하지 당신이 백그라운드에서 무슨 일을하는지 동기화 할 수 있습니다. 나는 그것이 당신이 의미하는 바가 아닌 것으로 의심합니다.

는 당신은 아마 구성 : 그것은 완전히 다른 동작이 매우 비슷하지만, 결과

dispatch_async(queue, ^{ 
    @synchronized(myID) { 
     // do stuff with myID 
    } 
}); 

. 이제 배경 대기열로 발송 된 작업이 동기화되고 있습니다. 추가 정제로

이 (그리고 내가있을 수 있습니다 가정), 그때는 아마 최대한 @synchronized 블록 제한 싶어 블록이 가능 느린 파견 경우 :

dispatch_async(queue, ^{ 

    // do slow stuff in preparation for interacting with `myID` 

    @synchronized(myID) { 
     // quickly do stuff with myID 
    } 

    // do anything else here 
}); 

당신이 만약을 @synchronized 블록 내의 모든 배경 블록을 수행하면 백그라운드로, 즉 주 큐에 미치는 영향을 최소화하기 위해 전체 목적을 무시할 수 있습니다. 이 마지막 변환은 그 문제를 완화합니다.

마지막 관찰 결과, 직렬 대기열 (또는 장벽으로 업데이트하는 비전 역동적 대기열)이있는 경우에는 잠금을 사용할 필요가없는 한 기술로 자주 사용됩니다 myID에 대한 모든 업데이트 및 질의가 해당 큐에 전달됩니다. 동시성 프로 그래 V 안내서에서 Eliminating Lock-Based Code을 참조하십시오.

+0

"메인 대기열에 미치는 영향을 최소화하십시오"라고 말하면 백그라운드 프로세스가 더 오래 걸릴 것입니다. 작업이 백그라운드 대기열에서 여전히 수행되고 있으며 작업이 백그라운드 대기열에서 수행되지 않습니다. UI를 차단하십시오. – Ixx

+0

@Ixx - 아니, 제 말은 (a) 백그라운드 스레드에서'@synchronized' 블록 내에서 시간을 많이 소비한다면, (b) 메인 쓰레드가'myID'에 접근 할 필요가 있다면 (따라서'@synchronized'도 사용해야 만합니다.) 백그라운드'@ synchronized' 블록은 메인 쓰레드를 쉽게 막을 수 있습니다. 전부 대기열에 물건. 따라서, 백그라운드 스레드가'@synchronized'를 수행해야하는 경우, 가능하면 @synchronized 블록 밖에서 시간 소모적 인 작업을 가능한 한 빨리 수행 할 수 있도록하십시오. – Rob