Finish First, Then Publish: The Safe Publication Pattern
Build shared state locally, confirm success, then assign it last in one write. This pattern avoids exposing half-initialized objects to other threads.
Finish First, Then Publish: Assign Shared State Only After Success
When a synchronization primitive only provides isolation, not rollback, atomicity has to be built manually. The rule fits in one sentence: defer assignment to the shared field until last.
It’s just three steps:
- Do the work into a local variable.
- Confirm it succeeded.
- Only then assign it to the shared variable — last, in a single write.
Never publish an object that’s only half-initialized: another thread might read that half-finished state. This is “safe publication” — a reference should only become visible once the object is fully constructed.
session = requests.Session() # build in a local variable
resp = session.post(LOGIN_URL, ...) # succeed first
resp.raise_for_status()
self.session = session # publish only after success, single write
If post() throws, no shared state has been touched → the next thread won’t read torn state either.
The pitfall people fall into most in practice is writing the order backwards: putting self.session = requests.Session() up front, then running a login that might fail. If that login throws, the shared field is already pointing at a session that never finished logging in.
Publishing a reference tells other threads “this is done” — so make sure it actually is.
References:
- https://wiki.sei.cmu.edu/confluence/display/java/TSM03-J.+Do+not+publish+partially+initialized+objects
- Java Concurrency in Practice, Ch. 3.5, Safe Publication
Related: see the mutex vs. ACID isolation breakdown, how with lock: guarantees release on exception, or go back to the four-lesson overview on making login thread-safe.