/, Tech/Thread Synchronization with Lock in Python

Thread Synchronization with Lock in Python

Why Lock() ?

  • When 2 or more operations belonging to concurrent threads try to access the shared memory, a race condition can occur
  • The easiest way to get around the race conditions is the use of a lock
  • The operation of a lock is simple when a thread wants to access a portion of shared memory, it must necessarily acquire a lock on that portion prior to using it.
  • After completing its operation, the thread must release the lock that was previously obtained.
  • The impossibility of incurring races is critical as the need of the lock for the thread.

Deadlock

  • A deadlock occurs due to the acquisition of a lock from different threads
  • It is impossible to proceed with the execution of operations

Advantages of Lock()

  • It allows us to restrict the access of a shared resource to a single thread or a single type of thread at a time
  • Before accessing the shared resource of the program, the thread must acquire the lock and must then allow any other threads access to the same resource.
import threading

shared_resource_with_lock = 0

shared_resource_with_no_lock = 0

COUNT = 10000

shared_resource_lock = threading.Lock()

# Lock Management

def increment_with_lock():
    global shared_resource_with_lock
    for i in range(COUNT):
        shared_resource_lock.acquire()
        shared_resource_with_lock += 1
        shared_resource_lock.release()

def decrement_with_lock():
    global shared_resource_with_lock
    for i in range(COUNT):
        shared_resource_lock.acquire()
        shared_resource_with_lock -= 1
        shared_resource_lock.release()

def increment_without_lock():
    global shared_resource_with_no_lock
    for i in range(COUNT):
        shared_resource_with_no_lock += 1

def decrement_without_lock():
    global shared_resource_with_no_lock
    for i in range(COUNT):
        shared_resource_with_no_lock -= 1

if __name__ == "__main__":
    t1 = threading.Thread(target = increment_with_lock)
    t2 = threading.Thread(target = decrement_with_lock)
    t3 = threading.Thread(target = increment_without_lock)
    t4 = threading.Thread(target = decrement_without_lock)

    t1.start()
    t2.start()
    t3.start()
    t4.start()
    t1.join()
    t2.join()
    t3.join()
    t4.join()

    print("the value of shared variable with lock management is %s"\
          %shared_resource_with_lock
          )

    print("the value of shared variable with race condition is %s" \
          %shared_resource_with_no_lock)
  • Locks have two states: Locked and unlocked
  • We have two methods that are used to manipulate the locks: acquire() and release()

Rules

  • If the state is unlocked, a call to acquire() changes state to locked
  • If the state is locked, a call to acquire() blocks until another thread calls release()
  • If the state is unlocked, a call to release() raises a Runtime Error exception
  • If the state is locked, a call to release() changes the state to unlocked

Disadvantages

  • The locks are subject to harmful situations of deadlock
  • They have many other negative aspects for the application as a whole
  • It also limits the scalability of the code and its readability
  • The use of a lock is in conflict with the possible need to impose the priority of access to the memory shared by the various processes
  • An application containing a lock presents considerable difficulties when searching for errors or debugging
By |2018-12-02T23:46:11+00:00December 2nd, 2018|Categories: Python, Tech|Tags: , , , , |0 Comments

About the Author:

Pratik Kataria is currently learning Springboot and Hibernate. Technologies known and worked on: C/C++, Java, Python, JavaScript, HTML, CSS, Wordpress, Angular, Ionic, MongoDB, SQL and Android. Softwares known and worked on: Adobe Photoshop, Adobe Illustrator and Adobe After Effects.

Leave A Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.