On Dec 23, 7:30 am, Duncan Booth <duncan.bo...@invalid.invalid> wrote: > Aaron Brady <castiro...@gmail.com> wrote: > > Th.1 Th.2 > > a=X > > a=Y > > a=Z > > > You are saying that if 'a=Z' interrupts 'a=Y' at the wrong time, the > > destructor for 'X' or 'Y' might not get called. Correct? In serial > > flow, the destructor for X is called, then Y. > > No, the destructors will be called, but the destructors can do pretty much > anything they want so you can't say the assignment is atomic. This isn't > actually a threading issue: you don't need multiple threads to experience > werid issues here. If you do strange things in a destructor then you can > come up with confusing code even with a single thread.
I see. What about del a a= Z Then, can we say 'a=Z' is atomic? At least, it eliminates the destructor issue you raise. > >> Other nasty things can happen if you use dictionaries from multiple > >> threads. You cannot add or remove a dictionary key while iterating over > >> a dictionary. This isn't normally a big issue, but as soon as you try to > >> share the dictionary between threads you'll have to be careful never to > >> iterate through it. > > > These aren't documented, IIRC. Did you just discover them by trial > > and error? > > It is documented, but I can't remember where for Python 2.x. For Python 3, > PEP 3106 says: "As in Python 2.x, mutating a dict while iterating over it > using an iterator has an undefined effect and will in most cases raise a > RuntimeError exception. (This is similar to the guarantees made by the Java > Collections Framework.)" I infer that d.items() holds the GIL during the entire operation, and it's safe to put in a thread. It is merely using an iterator that is unsafe. (Python 3.0 removed d.items(), leaving only the iterator, I understand.) I'm looking at the code, and I don't see where the size is safely checked. That is, can't I sneak in an add and a remove during iteration, so long as it doesn't catch me? I'm looking at 'dict_traverse': while (PyDict_Next(op, &i, &pk, &pv)) { Py_VISIT(pk); Py_VISIT(pv); } No locks are acquired here, though I might have missed acquiring the GIL somewhere else. In the OP's example, he wasn't changing the size of the dict. -- http://mail.python.org/mailman/listinfo/python-list