0

Suppose I have some dictionary in python and I want to be able to guarantee a value for a given key is only set once.

I know I can do this by checking has_key(newkey), followed by dict[newkey]=value.

This works fine for a single-threaded application:

d = { 1:'spam', 2:'eggs' }

def add_entry( key, val ):
    if not d.has_key(key):
        d[key] = val
    else:
        raise Exception('Nice try, but value with key '%s' already exists' %str(key))

# Succeeds
add_entry( 3, 'ham' )

# Fails with exception
add_entry( 2, 'cheese' )

However, I want to achieve this same behavior from a multi-threaded application.

What's a thread safe impl of add_entry above? Is there a builtin method / data structure I'm missing that just does this? Or do I need to use an explicit lock?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Brian McFarland
  • 9,052
  • 6
  • 38
  • 56
  • @Martijn - The question you linked to was asked in 2009... I did see that in searching for an answer, but a lot changed from 2.6 (latest at the time) to 2.7 (first released in 2010). I'm still not 100% sure from the accepted answer if I can safely do `if val != d.setdefault(key,val): raise Exception` or if the lock is necessary. – Brian McFarland Dec 29 '15 at 21:36
  • `dict.setdefault` is defined in C ([here](https://hg.python.org/cpython/file/default/Objects/dictobject.c#l2382)), so the GIL will protect its use in parallel code running in cpython. If you want to write code that will run safely in other interpreters or in some future version of cpython where the GIL doesn't apply, you should use explicit locking. – Blckknght Dec 29 '15 at 22:34
  • 1
    Nothing changed in that respect; you can always check the [*What's New* documentation](https://docs.python.org/2/whatsnew/2.7.html) if you want to be sure. `d.setdefault()` is implemented in C, so apart from loading all the expressions before the call the only thing that could still cause a thread switch is if `key` is a Python-defined class with a `__hash__` or `__eq__` method. – Martijn Pieters Dec 29 '15 at 22:34
  • @Blckknght: not if `key` is a custom type and implements a `__hash__` or `__eq__` method. – Martijn Pieters Dec 29 '15 at 22:35
  • @MartijnPieters - thanks for the thorough explanation & C reference. In my use case, the objects stored are C-defined/built-in data, but given the precaution about Python-defined classes, I think I'll go with an explicit lock instead to make the code a little more "future proof". – Brian McFarland Jan 04 '16 at 16:51

0 Answers0