- 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.
- Docker技術(shù)入門與實戰(zhàn)(第3版)
- SOA實踐
- Reactive Programming with Swift
- 21天學(xué)通C++(第6版)
- Raspberry Pi 2 Server Essentials
- Jupyter數(shù)據(jù)科學(xué)實戰(zhàn)
- Python之光:Python編程入門與實戰(zhàn)
- Keras深度學(xué)習(xí)實戰(zhàn)
- Unity 2018 Shaders and Effects Cookbook
- C#程序設(shè)計教程(第3版)
- Regression Analysis with Python
- Laravel Application Development Blueprints
- Web前端開發(fā)最佳實踐
- 你好!Java
- 絕密原型檔案:看看專業(yè)產(chǎn)品經(jīng)理的原型是什么樣