title: how to synchronize threads using Lock object
body: <p>in the below code i am learning how to synchronize threads. i referred to several tutorials. as stated in the tutorials, i must use Lock() object so to call</p>
  <pre><code>.acquire() and .release()
  </code></pre>
  <p>I coded the below code but i always receive the following error:
  please tell me how to synchronize threads properly</p>
  <pre><code>  self._target(*self._args, **self._kwargs)
    File &quot;m:\python lessons\ThreadsWithSync.py&quot;, line 42, in isNumPrime
        lock.acquire()
    NameError: name 'lock' is not defined
        lock.acquire()
        lock.acquire()
    NameError: name 'lock' is not defined
  </code></pre>
  <p><strong>code</strong>:</p>
  <pre><code>import threading
  from threading import Lock, Thread
  import logging
  import time
  from random import seed
  from random import randint
  
  class ThreadsWithSync(threading.Thread):
      lock = Lock()
      def __new__(cls):
      &quot;&quot;&quot;
      For object creation
      &quot;&quot;&quot;
      print(&quot;cls: %s&quot;%(cls))
      #cls.onCreateObject()
      instance = super(ThreadsWithSync, cls).__new__(cls)
      #print(&quot;instace: %s&quot;%(instance.__repr__)) #activate this line whenever an informative and descriprtive text about the instance is needed to be displayed
      return instance
      
      def __init__(self):
      &quot;&quot;&quot;
      For object initialization
      &quot;&quot;&quot;
      #print(&quot;self: %s&quot;%(self)) 
      threading.Thread.__init__(self) #to initialize the super class
      print(&quot;self: %s&quot;%(self))
      #seed(.1) #when set to integer number, the randomly generated numbers will be the same. ommit this to get different random numbers each run.
  
      @classmethod
      def onCreateObject(cls):
      &quot;&quot;&quot;
      This will be invoked once the creation procedure of the object begins.
      &quot;&quot;&quot;
  
      def __repr__(self):
      &quot;&quot;&quot;
      similar to toString in Java
      &quot;&quot;&quot;
      return &quot;\n__class__: &quot; + repr(self.__class__) +&quot;\n__new__:&quot; + repr(self.__new__) + &quot;\n__str__: &quot; + repr(self.__str__) + &quot;\n__sizeof__: &quot; + repr(self.__sizeof__)
      
      def isNumPrime(self, targetNum):
      lock.acquire()
      if targetNum == 0 or targetNum == 1:
          print(&quot;thread name: %s targetNum passed to method, will return false: %s&quot;%(threading.current_thread().name,targetNum))
          return False
  
      if targetNum == 2:
          print(&quot;targetNum passed to method will return true: %s&quot;%(targetNum))
          return True
  
      isPrim = True
      for i in range(3,targetNum):
          #print(&quot;thread name: %s in loop: targetNum: %s&quot;%(threading.current_thread().name,targetNum)) 
          if targetNum % i == 0:
              isPrim = False
              break
      print(&quot;%s-&gt; is %s a prime : %s&quot;%(threading.current_thread().name,targetNum, isPrim)) 
      return isPrim
  
      def spawnThread(self):
      if __name__ == &quot;__main__&quot;:
          self.main()
  
      def main(self):
      while True:
          thread_1 = threading.Thread(group = None, target = self.isNumPrime, name='Thread_1', args = (), kwargs=dict(targetNum=randint(0,100)), daemon = None)
          thread_2 = threading.Thread(group = None, target = self.isNumPrime, name='Thread_2', args = (), kwargs=dict(targetNum=randint(0,100)), daemon = None)
          thread_3 = threading.Thread(group = None, target = self.isNumPrime, name='Thread_3', args = (), kwargs=dict(targetNum=randint(0,100)), daemon = None)
          thread_4 = threading.Thread(group = None, target = self.isNumPrime, name='Thread_4', args = (), kwargs=dict(targetNum=randint(0,100)), daemon = None)
          thread_1.start()
          thread_2.start()
          thread_3.start()
          thread_4.start()
          time.sleep(3)
  
  t1 = ThreadsWithSync()
  t1.spawnThread()
  </code></pre>