.. include:: <mmlalias.txt>


Race Conditions, and Mutexes
============================

.. contents::
   :local:

.. sidebar::

   **Documentation**

   * :doc:`python:library/threading`

Mother of All Race conditions: Integer Increment
------------------------------------------------

.. literalinclude:: code/race-condition.py
   :caption: :download:`code/race-condition.py`

.. code-block:: console

   $ python code/race-condition.py
   final value: 14784035

|longrightarrow| *Load Modify Store Conflict*

Load Modify Store Conflict
--------------------------

====== ====     ====== ====  ===========
**CPU A**         **CPU B**  **Memory**
-----------     -----------  -----------
Instr   Loc     Instr   Loc  Glob
load     42     -       -     42 
-        42     load    42    42 
inc      43     -       -     42 
-        43     inc     43    42 
-        43     store   43    43 
store    43     -       43    43 
====== ====     ====== ====  ===========

Solution: Mutex (Explicit Acquire/Release)
------------------------------------------

* Mutex (for "MUTual EXclusion"), short: ``Lock``
* Best analogy: toilet door lock

.. literalinclude:: code/mutex.py
   :caption: :download:`code/mutex.py`

.. code-block:: console
   
   $ python code/mutex.py
   final value: 20000000

Solution: Mutex (``with`` Statement)
------------------------------------

* Calling ``lock.acquire()`` and ``lock.release()`` manually
* |longrightarrow| what if exception is raised in the middle? (Well,
  integer increments don't usually raise one; you get the point
  though.)

|longrightarrow| This is what the ``with`` statement is there fore
(``threading.Lock`` can act as a *context manager*)

.. literalinclude:: code/mutex-with.py
   :caption: :download:`code/mutex-with.py`