ArticleDirectory
Deadlock
When multiple resources are shared between threads, if the two threads occupy a part of resources and wait for the resources of the other side at the same time, a deadlock will occur. Although deadlocks rarely occur, once they occur, the application will stop responding. The following is an example of a deadlock:
# Encoding: UTF-8
Import Threading
Import Time
Class 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
If Mutexa. Acquire (1 ):
MSG = self. Name + ' Got RESA '
Print MSG
Mutexa. Release ()
Mutexb. Release ()
Def Run (Self ):
Self. do1 ()
Self. do2 ()
Resa = 0
Resb = 0
Mutexa = threading. Lock ()
Mutexb = threading. Lock ()
Def Test ():
For I In Range (5 ):
T = mythread ()
T. Start ()
If _ Name __ = ' _ Main __ ' :
Test ()
Execution result:
Thread-1 got RESA
Thread-1 got resb
Thread-1 got resb
Thread-1 got RESA
Thread-2 got RESA
Thread-2 got resb
Thread-2 got resb
Thread-2 got RESA
Thread-3 got RESA
Thread-3 got resb
Thread-3 got resb
Thread-3 got RESA
Thread-5 got RESA
Thread-5 got resb
Thread-5 got resb
Thread-4 got RESA
At this time, the process has died.
Reentrant lock
A simpler deadlock occurs when a thread "iterates" to request the same resource, which directly causes a deadlock:
Import Threading
Import Time
Class Mythread (threading. Thread ):
Def Run (Self ):
Global Num
Time. Sleep (1)
If Mutex. Acquire (1 ):
Num = num + 1
MSG = self. Name + ' Set num ' + STR (Num)
Print MSG
Mutex. Acquire ()
Mutex. Release ()
Mutex. Release ()
Num = 0
Mutex = threading. Lock ()
Def Test ():
For I In Range (5 ):
T = mythread ()
T. Start ()
If _ Name __ = ' _ Main __ ' :
Test ()
To support multiple requests to the same resource in the same thread, Python provides the "reentrant lock": Threading. rlock. Rlock internally maintains a lock and a counter variable. Counter records the number of acquire times so that resources can be require multiple times. Resources can be obtained only when all acquire of a thread is release. In the above example, if you use rlock instead of lock, no deadlock will occur:
Import Threading
Import Time
Class Mythread (threading. Thread ):
Def Run (Self ):
Global Num
Time. Sleep (1)
If Mutex. Acquire (1 ):
Num = num + 1
MSG = self. Name + ' Set num ' + STR (Num)
Print MSG
Mutex. Acquire ()
Mutex. Release ()
Mutex. Release ()
Num = 0
Mutex = threading. rlock ()
Def Test ():
For I In Range (5 ):
T = mythread ()
T. Start ()
If _ Name __ = ' _ Main __ ' :
Test ()
Execution result:
Thread-1 Set num to 1
Thread-3 set num to 2
Thread-2 set num to 3
Thread-5 set num to 4
Thread-4 set num to 5