2016-07-01 9 views
1

私はラインで次のコードを複数回アプリのクラッシュを実行すると:dispatch_async更新変数クラッシュ - スレッドセーフ

res.append(I)

エラーは致命的なエラーがある:負の数とUnsafeMutablePointer.destroy

をデバッグするmalloc_error_breakにブレークポイントを設定 か ポインタ解放されが割り当てられていない***はdispatch_async内のグローバル変数を更新するために、正しくないですか?

クラスのViewController:の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は、スレッドセーフではないので、アレイへの書き込みは、atomicを確保する必要があるとき。

したがって、高性能ロック: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

あなたが言及している多くの変数がマルチスレッドセーフであるかどうかはわかりません。そうでない場合は、一般的に2種類の処理方法があります。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

関連する問題