7 ms·
I don’t see how the GIL makes writing thread safe software any easier. The GIL might prevent two Python threads executing simultaneously, but it doesn’t change
by avianlyric 5y ago
I don’t see how the GIL makes writing thread safe software any easier. The GIL might prevent two Python threads executing simultaneously, but it doesn’t change the fact that a Python thread can be preempted, meaning your global state can change at any point during execution without warning.
Most of the issues with multi-threading come from concurrency, not parallelism. The GIL allows concurrency, you just don’t get any of the advantages of parallelism, which is normally the reason for putting up with the complexity concurrency creates.
- dleslie 5y ago> The GIL might prevent two Python threads executing simultaneously, but it doesn’t change the fact that a Python thread can be preempted, meaning your global state can change at any point during execution without warning. That thread behavior is enough to reduce the likelihood of races and collisions; particularly if the critical sections are narrow.
- laserlight 5y agoI wouldn’t call it thread-safe when race conditions are possible.
- jldugger 5y agoThen we need a term for when code race conditions are possible but rare enough that nobody using the software notices. thread-timebomb?
- phkahler 5y ago>> then we need a term for when code race conditions are possible but rare enough There is no such thing as "rare enough". Random or probabilistic bugs are one of the worst things software can have.
- nuerow 5y ago> Then we need a term for when code race conditions are possible but rare enough that nobody using the software notices. thread-timebomb? There's already a term for that: not thread-safe. The definition of thread safety does not include theoretical or practical assessments regarding how frequent a problem can occurr. It only assesses whether a specific class of problems is eliminated or not.
- jldugger 5y ago>The definition of thread safety does not include theoretical or practical assessments regarding how frequent a problem can occur. Well, obviously. The challenge I am putting forth on HN is to meaningfully describe _usable_ thread-unsafe software. If you've spent enough time outside university, you'll be aware that there are all kinds of theoretical race conditions that are not triggered in practical use.
- klyrs 5y agoIf you've worked at industrial scale, you'll be aware that even the most theoretical-seeming race condition will be triggered frequently.
- jldugger 5y ago> If you've worked at industrial scale, Fun fact, I actually do! It's from that perspective I wrote that: every time you perturb the software environment, a new set of bugs that didn't happen in the old env before arises.
- The_Colonel 5y agoThat reminds me how I was called to fix some Java service, which was successfully in production for 10 years with hardly any incident, but it suddenly started crashing hard, all the time. It was of course a thread safety issue (concurrent non-synchronized access to hashmap) which laid dormant for 10 years only to wreak havoc later. Nothing obvious changed (it was still running a decade old JRE), perhaps it was a kernel security patch, perhaps a RAM was replaced or even just the runtime data increased/changed in some way which woke up this monster.
- formerly_proven 5y agoHeisenbug.
- dkersten 5y agoThat's not useful. If you have a race condition, you will eventually hit it and when you do, you may get incorrect results or corrupt data. Thread unsafe is thread unsafe, regardless how rare it appears to be. Also, rare on one computer (or today's computer) might not be rare on another (tomorrows faster one for example). These types of bugs are also very hard to detect. You might not know your data is corrupted. Reminds me of how bad calculations in excel has cost companies billions of dollars, except now, the calculations could be "correct" and the error sitting dormant, just waiting for the right timings to happen. Much better to not make assumptions about the safety and think about it up front: if you are using multiple threads, you need to carefully consider your thread safety.
- Brian_K_White 5y agoThere is no such thing as "likely". A thing is either possible or not possible.
- kingofpandora 5y agoLikelihood refers to probability not possibility.
- Brian_K_White 5y agoThere is no such thing as probability. All there is is possible and not possible. I don't know how the point of the comment could be missed, but what I am saying is, it is a mistake, a rookie baby not-a-programmer not even any kind of engineer in any field, to even think in those sorts of terms at all. At least not in the platonic ideal worlds of math or code or protocol or systems design or legal documents, etc. Physical events have probability that is unavoidable. How fast does the gas burn? "Probably this fast" There is no excuse for any coder to even utter the word "likely". The ONLY answers to "Is this operation atomic?" or "Is this function correct?" or "Does this cpu perform division correctly?" Is either yes or no. There is no freaking "Most of the time." "Likely" only exists in the realm of user data and where it is explicitly created as part of an algorythm.
- yholio 5y agoThere are whole branches of computer science and IT dedicated to reducing the likelihood of unpleasant outcomes: cryptography, security, disaster recovery etc. You cannot guarantee your public key algorithm is impossible to break, but you can use keys long enough that an attacker has an arbitrarily low chance of succes with the best known methods. You cannot prove your program is bug free, outside of highly specialized fields like aircraft control, but you can build a multi-layered architecture that can reduce the likelihood of successful intrusion. You cannot prevent a EMP bomb from wiping all your hard-drives at once, but you will likely maintain integrity of your database for uncorrelated hardware errors. "Likely" is a tool that works in the real world. If you will chase mathematic certainty, your competition will likely eat your lunch. Where you might be correct is that "unlikely" is very close to "likely" in the particular topic of thread safety, you just need a sufficiently large userbase with workloads and environments sufficiently different from your test setup.
- avianlyric 5y agoThat just means the GIL is good at hiding concurrency bugs. It doesn’t make writing correct code any easier. Arguably you could say it makes writing correct concurrent code harder, because it’ll take significantly longer for concurrency bugs cause errors.
- chacham15 5y agoThere are certain classes of errors that it prevents. E.g: Thread1: a = 0xFFFFFFFF00000000 Thread2: a = 0x00000000FFFFFFFF One might think that the two possible values of a if those are run concurrently are 0xFFFFFFFF00000000 and 0x00000000FFFFFFFF. But actually 0x0000000000000000 and 0xFFFFFFFFFFFFFFFF are also possible because the load itself isnt atomic. The GIL (AFAICT) will prevent the latter two possibilities.
- intrepidhero 5y agoBut if you're writing to the same object from two different threads you're going to have undefined behavior regardless of the GIL, yes?
- NovemberWhiskey 5y agoNot really. If you're doing an atomic write to the same object from two different threads, you're going to have one win the race and the other lose. That may be a bug in your code, but it's not undefined behavior at the language level.
- ajkjk 5y agoIt prevents classes of errors, such as, as the parent mentioned, non-atomic writes to individual variables.
- fulafel 5y agoNo. The L in GIL stands for lock. So only the thread that holds it can write or read from the object, and the behavior is well defined at the C level, because C lock acquire and release operations are defined to be memory barriers.
- dkersten 5y agoBut when each thread reads the variable, you have no control over which value you see, since you don't control when each thread gets to run. So its undefined in the sense that you don't know which values you will get: a thread might get the value it wrote, or the value the other thread wrote. The threads might not get the same value either. The GIL exists to protect the interpreters internal data, not your applications data. If you access mutable data from more than one thread, you still need to your own synchronisation.
- dehrmann 5y agoIt's more cpython than the GIL, but it lets you get away with using += and certain dict operations without locks.
- hexane360 5y agoIs this true? It looks like += compiles to four bytecode instructions: two loads, an increment, and a store. It should be possible for a thread to get paused after the load but before the store, resulting in a stale read and lost write. Some more discussion here: https://stackoverflow.com/questions/1717393/is-the-operator-thread-safe-in-python https://stackoverflow.com/questions/1717393/is-the-operator-...
- dehrmann 5y agoMaybe it's just certain collection operations, then.
- detaro 5y agoAnd the proposal clearly addresses adjusting those to maintain the expected guarantees.
- pansa2 5y agoWith the GIL, for an int i, `i += 1` is not thread-safe, but IIRC for a list l, `l += [1]` (i.e. extend) is. Presumably this patch changes the list implementation in some way so that the extend operation remains thread-safe without the GIL.
- stefan_ 5y agoFrom running the same software on two moderately powerful embedded systems, one single-core and one multi-core, the latter is a lot more reliable in immediately exposing races and concurrency issues.