[swift-users] Recommendation for thread-safe dictionary

Pelaia II, Tom pelaiata at ornl.gov
Thu Dec 10 12:06:54 CST 2015


But isn’t that really a problem with that use case rather than the concurrent dictionary itself? There are a lot of bad things one can do with almost any code. For example, one can naively use the standard library dictionary in subtle, unsafe ways with concurrency and get into trouble.

Of course “+-" would be a bad idea to do in this context. Indeed, I am using this concurrent dictionary in a special use case, and I would never do the “+=“ operation as you suggest. It’s not even relevant in my code. I am just using this concurrent dictionary to keep track of concurrent events being completed and posted from different threads. When the event completes it gets put into the dictionary with the value being the immutable result. Alternatively, I could have put the concurrency code outside of the dictionary, but in my case that made for awkward access and opened the possibility of accidentally referencing the dictionary directly in an unsafe way. The safest option for me was to create the concurrent dictionary and the subscript allowed the code to be easier to read and write.
_____________________________________________________________________________________
Thomas Pelaia II, Ph.D.  | Applications Leader, Accelerator Physics, Research Accelerator Division
Spallation Neutron Source  |  Oak Ridge National Lab, Building 8600, MS-6462, Oak Ridge, TN 37831
phone: (865) 414-7960  | FaceTime: t6p at ornl.gov<mailto:t6p at ornl.gov> |  fax: (865) 574-6617  |  homepage: http://www.ornl.gov/~t6p

On Dec 10, 2015, at 12:44 PM, Dmitri Gribenko <gribozavr at gmail.com<mailto:gribozavr at gmail.com>> wrote:

On Thu, Dec 10, 2015 at 9:24 AM, Pelaia II, Tom via swift-users <swift-users at swift.org<mailto:swift-users at swift.org>> wrote:
/* provide subscript accessors */
subscript(key: KeyType) -> ValueType? {
get {
var value : ValueType?
dispatch_sync(self.queue) { () -> Void in
value = self.internalDictionary[key]
}
return value
}

set {
setValue(newValue, forKey: key)
}
}

Please don't do this, unless you have a very special use case.  This is inherently racy on high level, even though it is safe in the language.  Consider two threads operating on a shared ConcurrentDictionary<Int, Int>:

d[42] += 1

Here's what the code compiles into:

var tmp = d.subscript_get(42)
tmp += 1
d.subscript_set(42, tmp)

The 'get' and 'set' operations are atomic, but the whole sequence isn't.  The results of operations that other threads execute during "tmp += 1" will be overwritten by the following 'subscript_set'.

Dmitri

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr at gmail.com<mailto:gribozavr at gmail.com>>*/

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20151210/6200723a/attachment.html>


More information about the swift-users mailing list