Examples of deadlocks, reentrant locks, and mutexes in Python

Source: Internet
Author: User
One, deadlock

Simply put, a deadlock is a resource that is called multiple times, and multiple callers fail to release the resource, which creates a deadlock, with examples that illustrate two common deadlock scenarios.

1. Iteration Deadlock

The situation is that a thread "iteration" requests the same resource, which directly causes a deadlock:

Import Threadingimport Timeclass MyThread (threading. Thread):  def run (self):    global num    time.sleep (1)    if Mutex.acquire (1):      num = num+1      msg = self.name+ ' Set num to ' +str (num)      print msg      mutex.acquire ()      mutex.release ()      mutex.release () num = 0mutex = Threading. Lock () def test (): For  I in range (5):    t = MyThread ()    T.start () if __name__ = = ' __main__ ':  Test ()

In the example above, the first request for the resource in the If judgment of the run function is not released after the request, acquire again, and eventually unable to release, causing a deadlock. In this example, the two lines below the print are commented out and can be executed normally, but can also be resolved by a reentrant lock, which is mentioned later.

2, call each other deadlock

The deadlock in the previous example is caused by multiple calls within the same Def function, and in the other case, the same resource is called in two functions, waiting for the end of each other. If two threads occupy a portion of the resources and wait for each other's resources at the same time, a deadlock is created.

Import Threadingimport Timeclass MyThread (threading. Thread):  def do1 (self):    global ResA, Resb    if Mutexa.acquire ():       msg = self.name+ ' got ResA '       print Msg       if Mutexb.acquire (1):         msg = self.name+ ' got Resb '         print msg         mutexb.release ()       mutexa.release ( )  def do2 (self):    global ResA, Resb    if Mutexb.acquire ():       msg = self.name+ ' got Resb '       print msg< C15/>if Mutexa.acquire (1):         msg = self.name+ ' got ResA '         print msg         mutexa.release ()       mutexb.release ()  def run (self):    self.do1 ()    self.do2 () ResA = 0resB = 0mutexA = Threading. Lock () Mutexb = Threading. Lock () def test (): For  I in range (5):    t = MyThread ()    T.start () if __name__ = = ' __main__ ':  Test ()

The example of this deadlock is a little bit more complicated. Specific can be cut down.

Second, can be re-entry lock

To support multiple requests for the same resource in the same thread, Python provides a "reentrant lock": Threading. Rlock. Rlock internally maintains a lock and a counter variable, counter records the number of acquire, so that resources can be require multiple times. Until all the acquire of a thread are release, the other threads can get the resources. Here, for example 1, if you use Rlock instead of lock, a deadlock will not occur:

Import Threadingimport Timeclass MyThread (threading. Thread):  def run (self):    global num    time.sleep (1)    if Mutex.acquire (1):      num = num+1      msg = self.name+ ' Set num to ' +str (num)      print msg      mutex.acquire ()      mutex.release ()      mutex.release () num = 0mutex = Threading. Rlock () def test (): For  I in range (5):    t = MyThread ()    T.start () if __name__ = = ' __main__ ':  Test ()

The difference between this and the above example is threading. Lock () replaced by threading. Rlock ().

Third, mutual exclusion lock
The Python threading module has two types of locks: Mutex (threading). Lock) and reusable locks (threading. Rlock). The use of the two is basically the same, specifically as follows:

Lock = Threading. Lock () Lock.acquire () dosomething......lock.release ()

The use of Rlock is to modify Threading.lock () to threading. Rlock (). Easy to understand, first to segment code:

[Root@361way lock]# Cat lock1.py

#!/usr/bin/env python# coding=utf-8import Threading              # Importing Threading Module Import Time               # import Time Module class Mythread ( Threading. Thread):    # Create Class  def __init__ (Self,threadname) by inheritance:   # Initialize Method    # Call the parent class's initialization method    threading. thread.__init__ (self,name = threadname)  def run (self):             # Reload the Run method    Global x         # Use Global to indicate that x is a global variable    For I in range (3):      x = x + 1    time.sleep (5)     # Call the Sleep function, let the thread sleep 5 seconds    print XTL = []               # definition list for I in rang E:  t = mythread (str (i))        # class instantiation  tl.append (t)           # Add a Class object to the list x=0                 # assigns X to 0for I in TL:  

The results are different from what we think, and the results are as follows:

[Root@361way lock]# python lock1.py

30303030303030303030

Why are the results all 30? The key is the global row and the Time.sleep line.

1, since x is a global variable, the value of x after each loop is the result value after execution;

2, because the code is multi-threaded operation, so at the time of sleep waiting, the previous execution of the completed thread will wait here, and the subsequent process in the waiting time of 5 seconds to complete, waiting for print. Also because of the global principle, X is re-bin value. So the printed results are all 30;

3, easy to understand, you can try to sleep and other comments, you look at the results, you will find that there are different.

In the actual application, such as the crawler, there will be similar to sleep waiting for the situation. When there is a sequential or printed output of the front and back calls, the competition is now concurrent, resulting in a result or output disorder. This introduces the concept of lock, the above code modified, as follows:

[Root@361way lock]# Cat lock2.py

#!/usr/bin/env python# coding=utf-8import Threading              # Importing Threading Module Import Time               # import Time Module class Mythread ( Threading. Thread):          # Create Class  def __init__ (Self,threadname) by inheritance:         # Initialize Method    threading. thread.__init__ (self,name = threadname)  def run (self):             # Reload the Run method    Global x            # Use Global to indicate that x is a global variable    Lock.acquire ()           # Call Lock's Acquire method for    I in range (3):      x = x + 1    time.sleep (5)      # Call the Sleep function, Let the thread sleep for 5 seconds    print x    lock.release ()        # Call Lock's release method lock = Threading. Lock ()        # class instantiation TL = []             # definition list for I in range:  t = mythread (str (i))      # class instantiation  tl.append (t)       # will The class object is added to the list x=0            # assigns X to 0for I in TL:  i.start ()           # Run thread sequentially

The results of the implementation are as follows:

[Root@361way lock]# python lock2.py

36912151821242730

Locking results in blocking, and can cause large locks. will be sequentially output by the concurrent multithreading, if the subsequent threads are executed too quickly and need to wait for the previous process to finish before they end--the writing seems a bit like the concept of the queue, but in the lock of many scenarios can be resolved through the queue.

  • Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.