title: Python atomic access (related to threads)
body: <p>When you start using threads, you have to understand very well some things, mostly about synchronization of shared data. You have to use locks, rlocks, semaphores and so on. Is it write even with very simple shared data?</p>
  
  <p>For example, I have two threads that share a global resource, a simple boolean variable.</p>
  
  <pre><code>import threading
  import random
  import time
  
  active = True
  
  class T1(threading.Thread):
      def run(self):
          while active:
              print("Hello")      # do some work
              time.sleep(0.1)
  
  class T2(threading.Thread):
      def run(self):
          global active
          while random.random() &gt; 0.05:
              time.sleep(1)
          active = False
  
  t1, t2 = T1(), T2()
  t1.start()
  t2.start()
  t1.join()
  t2.join()
  </code></pre>
  
  <p>It seems it works, but does python guarantees it works? If yes, exactly for what reason it works?</p>
  
  <p>I have three answers.</p>
  
  <ol>
  <li>It works because the access of a boolean variable is always atomic (it can't be interrupted by another thread). In this case, what Python guarantees as atomic operation? Is the access of an integer, a list, a dictionary atomic?</li>
  <li>Python doesn't guarantee this code works every time. The solution is to use a lock to access active variable in both thread.</li>
  <li>It works because only one thread writes the variable. The other thread only reads it.</li>
  </ol>
  
  <p>Here it is another code:</p>
  
  <pre><code>import threading
  import random
  import time
  
  numbers = [3]
  
  class T1(threading.Thread):
      def run(self):
          while sum(numbers) % 3 == 0:
              print("Hello")      # do some work
              time.sleep(0.1)
  
  class T2(threading.Thread):
      def run(self):
          global active
          while random.random() &gt; 0.2:
              numbers.extend([1, 2])
              time.sleep(1)
          numbers.append(4)
  
  t1, t2 = T1(), T2()
  t1.start()
  t2.start()
  t1.join()
  t2.join()
  </code></pre>
  
  <p>Now could the <strong>single and "complex"</strong> instruction <em>numbers.extend([1, 2])</em> be interrupted by T1 thread? If this is the case, just after 1 is added but before 2 is added, T1 could stop unintentionally before T2.</p>