Created
October 18, 2019 10:52
-
-
Save kleviscipi/17d48261a1f4c82039d63fdcc953ae55 to your computer and use it in GitHub Desktop.
Resolve a race conditions example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from threading import Thread,Lock | |
| """ | |
| How ro resolve a Race Conditions in Python | |
| Python is one of programming languages which support multiprocess and multi-threads and this is prety cool. | |
| At the end python is not one of the best for parallel programming but lets see how we can use and resolve a common problem which is : Race Conditions | |
| Before,I show you an example, first we should be familiar with this concept: Mutual Exlusion, Lock, Race Conditions | |
| Mutual Exlusion ?: When tow or more processes/threads wants to access to a shared resources, and after thread has accessed that resource than block all others concurrent | |
| Lock ?: A thread before accesses a shared resource, should graph or acquired a Lock,at this point all other councurrent are waiting for release of tha Lock. | |
| Lock is released after thread has terminated it's eczecution time using that resource. | |
| Race Conditions: The mutual exlusion comes out for this purpose, to resolve race conditions. | |
| A race condition happens when tow or more parallel threads has accessed at the same time and updated a shared resource, that's mind it is not protected by a lock. | |
| """ | |
| # x = 1 # Shared resource | |
| # def fibonaci(n): | |
| # if n<=2 : return 1 | |
| # return fibonaci(n-1) + fibonaci(n-2) | |
| # def firstFibonaci(): | |
| # global x | |
| # print("firstFibonaci resource is {} \n".format(x) ) | |
| # while x <= 10: | |
| # print(fibonaci(x)) | |
| # x+=1 | |
| # def secondFibonaci(): | |
| # global x | |
| # print("secondFibonaci resource is {} \n".format(x) ) | |
| # while x <= 10: | |
| # print(fibonaci(x)) | |
| # x+=1 | |
| # Parallel_1 = Thread(target=firstFibonaci) | |
| # Parallel_2 = Thread(target=secondFibonaci) | |
| # Parallel_1.start() | |
| # Parallel_2.start() | |
| # Parallel_1.join() | |
| # Parallel_2.join() | |
| """ | |
| I have created tow methods firstFibonaci and secondFibonaci and on each one, the shared resource x is in global scope. The shared resource is x and will be accessed by threads in parallel | |
| Technically the second method should not make any update to the shared resource, because it is incremented to 11 by the firstFibonaci method, but is it? | |
| This is the expected correct response | |
| $ /usr/bin/python race_condition.py | |
| firstFibonaci resource is 1 | |
| 1 | |
| 1 | |
| 2 | |
| 3 | |
| 5 | |
| 8 | |
| 13 | |
| 21 | |
| 34 | |
| 55 | |
| secondFibonaci resource is 11 | |
| But se how really is the response : | |
| $ /usr/bin/python race_condition.py | |
| firstFibonaci resource is 1 | |
| 1 | |
| secondFibonaci resource is 1 | |
| 1 | |
| 12 | |
| 35 | |
| 8 | |
| 13 | |
| 34 | |
| 2155 | |
| or another | |
| $ /usr/bin/python race_condition.py | |
| firstFibonaci resource is 1 | |
| 1 | |
| 1 | |
| 2 | |
| 3 | |
| 5 | |
| secondFibonaci resource is 6 | |
| 88 | |
| 13 | |
| 2134 | |
| 55 | |
| Why is happened that? | |
| That because the shared resource x is not protected by a Lock. Tow threads at the same time have accessed to that resource updating the state. | |
| Now, to resolve this race condition we go to use anther class of packet threading which is Lock. | |
| This class has tow main method : | |
| acquire: That means , the lock is graphed by a thread and all concurrent are blocked waiting for the release. | |
| release: That means, the lock is free ready for another thread. | |
| """ | |
| x = 1 # Shared resource | |
| lock_race = Lock() | |
| def fibonaci(n): | |
| if n<=2 : return 1 | |
| return fibonaci(n-1) + fibonaci(n-2) | |
| def firstFibonaci(): | |
| global x | |
| try: | |
| lock_race.acquire() | |
| print("firstFibonaci resource is {} \n".format(x) ) | |
| while x <= 10: | |
| print(fibonaci(x)) | |
| x+=1 | |
| finally: | |
| lock_race.release() | |
| def secondFibonaci(): | |
| global x | |
| try: | |
| lock_race.acquire() | |
| print("secondFibonaci resource is {} \n".format(x) ) | |
| while x <= 10: | |
| print(fibonaci(x)) | |
| x+=1 | |
| finally: | |
| lock_race.release() | |
| Parallel_1 = Thread(target=firstFibonaci) | |
| Parallel_2 = Thread(target=secondFibonaci) | |
| Parallel_1.start() | |
| Parallel_2.start() | |
| Parallel_1.join() | |
| Parallel_2.join() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment