Skip to content

Instantly share code, notes, and snippets.

@qiuyujx
Forked from couchdeveloper/DataRaceDemo.swift
Last active March 29, 2016 22:11
Show Gist options
  • Save qiuyujx/7173ea663308cc03f07e8a5c09cf4cba to your computer and use it in GitHub Desktop.
Save qiuyujx/7173ea663308cc03f07e8a5c09cf4cba to your computer and use it in GitHub Desktop.
import Foundation
func test(completion: (Int) -> ()) {
let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
//let queue = dispatch_queue_create("serial queue", DISPATCH_QUEUE_SERIAL)
var counter = 0
let grp = dispatch_group_create()
for _ in 0..<10000 {
/**
* Since "data race" need to satisfy 4 conditions
* - target the same location
* - are performed concurrently by two threads
* - are not reads
* - are not synchronization operations
* Therefore, we can break any one of above to avoid "data race".
* The most easy implemented one I think should be "synchronization" in swift.
* The code here presents how to avoid "data race" utilizing "synchronization"
*/
objc_sync_enter(counter) // Start sync
dispatch_group_enter(grp)
dispatch_async(queue) {
counter += 1
dispatch_group_leave(grp)
}
objc_sync_exit(counter) // Exit sync
}
dispatch_group_notify(grp, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
completion(counter)
}
}
let sem = dispatch_semaphore_create(0)
test() { counter in
print("counter: \(counter)")
// The counter should be 10000 - unless a data race occurred.
// With a concurrent queue, the variable `counter` is not synchronized and a data race will occure.
dispatch_semaphore_signal(sem)
}
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment