- Mastering Concurrency in Python
- Quan Nguyen
- 505字
- 2021-06-10 19:24:06
Example of deadlock handling
Let's look at a quick example in Python. Let's a take look at the Chapter04/example2.py file, as shown in the following code:
# Chapter04/example2.py
from threading import Lock
my_lock = Lock()
def get_data_from_file_v1(filename):
my_lock.acquire()
with open(filename, 'r') as f:
data.append(f.read())
my_lock.release()
data = []
try:
get_data_from_file('output2/sample0.txt')
except FileNotFoundError:
print('Encountered an exception...')
my_lock.acquire()
print('Lock can still be acquired.')
In this example, we have a get_data_from_file_v1()function that takes in the path to an external file, reads the data from it, and appends that data to a predeclared list called data. Inside this function, a lock object called my_lock, which is also predeclared prior to the function being called, is acquired and released as the parameter file is read before and after, respectively.
In the main program, we will try to call get_data_from_file_v1() on a nonexistent file, which is one of the most common errors in programming. At the end of the program, we also acquire the lock object again. The point is to see whether our programming could handle the error of reading a nonexistent file appropriately and gracefully with just the try...except block that we have.
After running the script, you will notice that our program will print out the error message specified in the try...except block, Encountered an exception..., which is expected, since the file could not be found. However, the program will also fail to execute the rest of the code; it will never get to the last line of code—print('Lock acquired.')—and will hang forever (or until you hit Ctrl + C to force-quit the program).
This is a deadlock situation, which, again, occurs when my_lock is acquired inside the get_data_from_file_v1() function, but since our program encountered an error before executing my_lock.release(), the lock was never released. This in turn caused the my_lock.acquire() line at the end of the program to hang, as the lock could not be acquired in any way. Our program hence could not reach its last line of code, print('Lock acquired.').
This problem, however, could be handled with a with statement easily and effortlessly. In the example2.py file, simply comment out the line calling get_data_from_file_v1() and uncomment the line calling get_data_from_file_v2(), and you will have the following:
# Chapter04/example2.py
from threading import Lock
my_lock = Lock()
def get_data_from_file_v2(filename):
with my_lock, open(filename, 'r') as f:
data.append(f.read())
data = []
try:
get_data_from_file_v2('output2/sample0.txt')
except:
print('Encountered an exception...')
my_lock.acquire()
print('Lock acquired.')
In the get_data_from_file_v2() function, we have the equivalent of a pair of nested with statements, as follows:
with my_lock:
with open(filename, 'r') as f:
data.append(f.read())
Since Lock objects are context managers, simply using with my_lock: would ensure that the lock object is acquired and released appropriately, even if an exception is encountered inside the block. After running the script, you will have the following output:
> python example2.py
Encountered an exception...
Lock acquired.
We can see that, this time, our program was able to acquire the lock and reach the end of the script gracefully and without errors.
- C++ Primer習題集(第5版)
- INSTANT OpenCV Starter
- C語言程序設計(第3版)
- Maven Build Customization
- INSTANT FreeMarker Starter
- 游戲程序設計教程
- Python高效開發實戰:Django、Tornado、Flask、Twisted(第2版)
- HTML5+CSS3網站設計基礎教程
- Node.js:來一打 C++ 擴展
- 蘋果的產品設計之道:創建優秀產品、服務和用戶體驗的七個原則
- Android項目實戰:手機安全衛士開發案例解析
- Citrix XenServer企業運維實戰
- 平面設計經典案例教程:CorelDRAW X6
- Android應用開發實戰(第2版)
- Neo4j 3.x入門經典