2016-07-01 3 views
1

Когда я запускаю следующий код несколько раз приложения аварии на линии:dispatch_async обновления переменной аварии - потокобезопасность

res.append (я)

Ошибка Фатальная ошибка: 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

Я не уверен, что много переменных, которые вы упомянули, являются многопоточными. В противном случае, как правило, два способа обработки: 1. использовать параллельную очередь + блокировку, как показано выше. 2. Использование последовательной очереди также может обеспечить атомный. Или вам нужно использовать другой план согласно вашему требованию. Вы можете прочитать эту статью статьи https://www.raywenderlich.com/60749/grand-central-dispatch-in-depth-part-1, может быть, полезно. – maquannene

+0

И эта быстрая версия https://www.raywenderlich.com/79149/grand-central-dispatch-tutorial-swift-part-1 – maquannene