2016-07-01 1 views
1

나는 줄에 다음 코드를 여러 번 응용 프로그램 충돌을 실행하면 :dispatch_async 갱신 변수 충돌 - 스레드 안전

res.append (I)

오류가 치명적인 오류는 다음과 같습니다 부정적인 카운트 UnsafeMutablePointer.destroy 또는 포인터가 해제 됨 *** 디버깅 할 malloc_error_break에 중단 점 설정

dispatch_async에서 전역 변수를 업데이트하는 것이 올바르지 않습니까?

클래스의 ViewController : 배열에 쓰기, atomic을 확인해야 할 때의 UIViewController {

var result = Array<Int>() 


func method(completion: (inner:() throws -> String)->Void){ 
    let group:dispatch_group_t = dispatch_group_create(); 
    let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) 
    var res = Array<Int>() 
    for i in 0..<4 { 
     dispatch_group_async(group,queue){ 
      res.append(i) 
      print(res) 
      print("Block\(i)");     
      var s = 0 
      for k in 0..<1000 { 
       s = 2+3 
      } 
      print("Block\(i)End"); 



     } 
    } 

    dispatch_group_wait(group, DISPATCH_TIME_FOREVER); 

    print("All background tasks are done!!"); 
    print(res) 
} 


override func viewDidLoad() { 
    super.viewDidLoad() 


    self.method() { (inner:() throws -> String) -> Void in 
     do { 
      let res = try inner() 
      print(res) 
     } catch let error { 
      print(error) 
     } 
    } 
} 
+0

기본 멀티 스레딩 문제 - 특별히 언급하지 않는 한 DONT는 개체가 스레드로부터 안전하며 다중 스레드에서 업데이트하지 않는다고 가정합니다. –

답변

1

그래, Array는 스레드 안전, 그렇게되지 않습니다.

그래서 고성능 잠금 : dispatch_semaphore_t를 추가 할 수 있습니다. 스레드 일정 시간이 많이 걸리는이며 성능 손실로 이어질 수 있기 때문에

func method(completion: (inner:() throws -> String)->Void){ 
    // add lock 
    let lock: dispatch_semaphore_t = dispatch_semaphore_create(1) 
    let group:dispatch_group_t = dispatch_group_create(); 
    let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) 
    var res = Array<Int>() 
    for i in 0 ..< 5 { 
     dispatch_group_async(group,queue){ 
      // lock 
      dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER) 
      res.append(i) 
      // unlock 
      dispatch_semaphore_signal(lock) 
      var s = 0 
      for k in 0..<1000 { 
       s = 2+3 
      } 
     } 
    } 

    dispatch_group_wait(group, DISPATCH_TIME_FOREVER); 

    print("All background tasks are done!!"); 
    print(res) 
} 

하지만 당신의 비동기 작업은 시간이 많이 걸리는 위 등의 작업을하지 않은 경우,주의는 멀티 스레드를 사용하지 않습니다.

+0

감사합니다. 이것은 단지 샘플 코드 일뿐입니다. 그렇다면 dispatch_async 내에서 전역 변수를 많이 사용하고 있다면 무엇이 가장 좋은 옵션입니까? NSOperationQueue를 사용해야합니까? – user584263

+0

당신이 언급 한 많은 변수가 다중 쓰레드에 안전한지 확실하지 않습니다. 그렇지 않은 경우, 일반적으로 두 가지 종류의 처리 방법이 있습니다. 1. 위와 같이 동시 대기열 + 잠금을 사용합니다. 2. 연속 대기열을 사용하면 원자도 보장 할 수 있습니다. 또는 귀하의 요구에 따라 다른 계획을 사용해야합니다. 이 기사 시리즈 (https://www.raywenderlich.com/60749/grand-central-dispatch-in-depth-part-1)를 읽으면 도움이 될 것입니다. – maquannene

+0

그리고이 Swift 버전 https://www.raywenderlich.com/79149/grand-central-dispatch-tutorial-swift-part-1 – maquannene