title: How to avoid data race with GCD DispatchWorkItem.notify?
body: <p>With Swift 3.1 on XCode 8.3, running the following code with the Thread Sanitizer finds a data race (see the write and read comments in the code):</p>
  
  <pre><code>  private func incrementAsync() {
      let item = DispatchWorkItem { [weak self] in
        guard let strongSelf = self else { return }
        strongSelf.x += 1 // &lt;--- the write
  
        // Uncomment following line and there's no race, probably because print introduces a barrier
        //print("&gt; DispatchWorkItem done")
      }
      item.notify(queue: .main) { [weak self] in
        guard let strongSelf = self else { return }
        print("&gt; \(strongSelf.x)") // &lt;--- the read
      }
  
      DispatchQueue.global(qos: .background).async(execute: item)
    }
  </code></pre>
  
  <p>This seems pretty strange to me as the documentation for the <code>DispatchWorkItem</code> mentions that it allows:</p>
  
  <blockquote>
    <p>getting notified about their completion</p>
  </blockquote>
  
  <p>which implies that the <code>notify</code> callback is called once the work item's execution is done.</p>
  
  <p>So I would expect that there would be a <code>happens-before</code> relationship between the <code>DispatchWorkItem</code>'s work closure and its notify closure. What would be the correct way, if any, to use a <code>DispatchWorkItem</code> with a registered <code>notify</code> callback like this that wouldn't trigger the Thread Sanitizer error?</p>
  
  <p>I tried registering the <code>notify</code> with <code>item.notify(flags: .barrier, queue: .main) ...</code> but the race persisted (probably because the flag only applies to the same queue, documentation is sparse on what the <code>.barrier</code> flag does). But even calling notify on the same (background) queue as the work item's execution, with the <code>flags: .barrier</code>, results in a race.</p>
  
  <p>If you wanna try this out, I published the complete XCode project on github here: <a href="https://github.com/mna/TestDispatchNotify" rel="nofollow noreferrer">https://github.com/mna/TestDispatchNotify</a></p>
  
  <p>There's a <code>TestDispatchNotify</code> scheme that builds the app without tsan, and <code>TestDispatchNotify+Tsan</code> with the Thread Sanitizer activated.</p>
  
  <p>Thanks,
  Martin</p>