On Thu, May 27, 2021 at 02:02:11PM -0700, Christopher Barker wrote:
My concern about thread safety is about how easy it would be to make it thread unsafe accidentally.
I'm intrigued what gives you the impression that Python functions and classes are, by default, thread safe.
The FAQ is a little bit misleading:
While it is true that builtin operations like list.append are thread safe, as soon as you have two of them, the compound operation is no longer thread safe unless guarded with a lock.
L.append(x) # thread-safe L.append(y) # L may have already been modified by another thread assert L[-2:] == (x, y) # may fail
And if L is a subclass of list or duck-typed, all bets are off. Even L.append may not be safe, if L is something other than an actual list.
Of course, there is a simple solution to that (apart from locks): don't use threads, or don't use shared mutable data. It is only the combination of concurrency with shared mutable state that is problematic. Remove either of those, and you're cool.
Function local static variables would be no worse in this regard than existing features: globals, mutable default values, classes with attributes, etc.
I'm not sure about closures and thread-safety, but closures come with their own pitfalls:
Sure, global is not thread safe, but it is well known that use of global is, to newbies, “bad”, and to more experienced programmers, “to be used with caution, understanding the risks”.
Is it well-known that writing classes is "bad", "to be used with caution, understanding the risks"?
One of the more disheartening things about the culture of this mailing list is the way new proposals are held to significantly higher standards that existing language and stdlib features do not meet.
This is a perfect example: it's not like regular Python functions and classes are thread-safe by default and this is introducing a new problem that is almost unique to static variables. Regular Python functions and classes are almost never thread-safe unless carefully written to be, which most people don't bother to do unless they specifically care about thread safety, which most people don't.
Any time you have a function with state, then it requires care to make it thread-safe. Doesn't matter whether that storage is a global, mutable defaults, instance or class attributes, or these hypothetical static variables.
Pure functions with no state or side-effects are thread-safe, but beyond that, every non-builtin, and some builtins, should be assumed to be unsafe unless carefully designed for concurrent use. It's not always obvious either:
Not thread-safe. Two threads can write to stdout simultaneously, interleaving their output.