Implementing Python Lock in Various Circumstances

Hello geeks and welcome to this article, we will cover python lock. Along with that, we will look at the need for python lock and how to implement it. To achieve all this, we will look at a couple of examples.

When one thread tries to modify a shared resource simultaneously, another thread is modifying it, which leads to a jumbled output. This condition is called a race condition, and it is one of the major problems that many programmers come across. To avoid it, we need to synchronize the thread. To achieve it, we can use the lock present in Python’s Threading module.

As we move ahead in this article, we will cover using the lock-in program. Also, we will cover the different states of the lock.

Lock object: Python Multithreading

In the threading module of python, a similar lock is used for effective multithreading. Through this, we can synchronize multiple threads at once. As discussed above, the lock is present inside python’s threading module. Also, it is used as a tool to synchronize threads. It has 2 different states

  • Locked
  • Unlocked

In order to attain the locked state, we use the acquire() method. Whereas to attain the unlocked state

We can use the release() method. Once the lock state is acquired, all the other attempts to access the thread are blocked. Hence by this, we eliminate any possibility of jumbled output.

How to Implement Python Lock

In this section, we will see how to implement a lock. In order to do so, we will consider a sample statement.

Suppose You are in the library where there is a stack of 10 books. The librarian implements a rule that another student picks it when one student keeps the book. In order, the stack number remains unchanged. But since the librarian is not paying close attention. So the students break this order, and now the sequence is broken. Now any number can keep the book simultaneously, while the same can keep it. But still, the stack number remains 10.

Now to solve this, we need to create two different threads. One thread keeps track of books taken, and the other one keeps.

Let us look at the first code:

import threading
stack= 10
def add_book():
    global stack
    for i in range(100000):
        stack = stack + 1
def take_book():
    global stack
    for i in range(100000):
        stack = stack - 1
thread1 = threading.Thread(target = add_book, args = ())
thread2 = threading.Thread(target = take_book, args = ())
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print(stack)
-54334

Here we can see that we get an error. Let use the discussed methods to get rid of this error.

import threading
stack= 10
lock=threading.Lock()
def add_book():
    global stack
    for i in range(100000):
        lock.acquire()
        stack = stack + 1
        lock.release()
def take_book():
    global stack
    for i in range(100000):
        lock.acquire()
        stack = stack - 1
        lock.release()
thread1 = threading.Thread(target = add_book, args = ())
thread2 = threading.Thread(target = take_book, args = ())
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print(stack)
10

Here we can see that we get the correct answer. To do so, we have to make some minute changes compared to the 1st code. At first, we have imported the threading module. Then we have defined our stack value. After which, we have defined the lock. Then we have written code for adding and taking the book from the stack. Also, we have used the acquire and release method over here. At last, we have used the print statement to get the output.

Multiprocessing Locks and using them to prevent data races

Multiprocessing is a build-in module of python. It helps us by preventing multiple files from printing to standard output. Also, it helps us by preventing data races, which means that when multiple threads can access shared data. And all at the same time try to change it. Besides this, it also prevents any data structure corruption.

import multiprocessing

def worker(lock):
    lock.acquire()
    print("Multi processing Lock") 
    lock.release()

lock = multiprocessing.Lock()

process = multiprocessing.Process(
    target=worker, args=[lock])
process.start()

lock.acquire()

lock.release()
Multi processing Lock

Here you can see a simple example related to multiprocessing Lock.

Difference Between Lock and Rlock

As we have already discussed, lock in this article. We understand that it is present in the threading module and avoids a jumbled output. Now let us look at what Rlock means and how it differs from the lock. Rlock is used to avoid the undesired blocking of the resource. The default lock method does not understand which threat the lock currently holds due to which all the threads are locked. This can make the process a bit slow so.

Understand aquire and release functions of a lock

Both the methods are amazingly useful while handling the threads. You can get an idea of whether the lock is locked or released. The following example will help you to understand –

Code:

>>> from threading import Lock
>>> y = Lock()
>>> y.locked()
False
>>> y.acquire()
True
>>> y.locked()
True

Explanation:

By creating a lock object in variable y, we’ve created a lock. You can check if the lock is locked by calling locked() method. Then calling acquire will acquire a lock. You can check it again by calling the locked method.

Conclusion

In this article, we have covered the Python lock. We tried to understand the need to use a lock and how it helps us. We also covered different states of lock and how to acquire them. To do so, we considered a sample problem. Through which we understood what difference does it makes to the output.

I hope this article was able to clear all doubts. But in case you have any unsolved queries feel free to write them below in the comment section. Done reading this, why not read about the normalize condition next.

Subscribe
Notify of
guest
2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Cathal Harte
Cathal Harte
3 years ago

lock=threading.Lock should be lock=threading.Lock()