https://pypi.python.org/pypi/lockfile/0.12.2 states:
This package is deprecated. It is highly preferred that instead of using this code base that instead
fasteners
_ oroslo.concurrency
is used instead
However, fasteners
is clear that is not thread safe:
Warning: There are no guarantees regarding usage by multiple threads in a single process
And I cannot find an example of using oslo.concurrency
.
There's also some suggestion that using flock
can resolve this situation, but the flock manual states:
(https://www.freebsd.org/cgi/man.cgi?query=flock&sektion=2)
The flock system call applies or removes an advisory lock on the file associated with the file descriptor fd. A lock is applied by specifying an operation argument that is one of LOCK_SH or LOCK_EX with the optional addition of LOCK_NB. To unlock an existing lock operation should be LOCK_UN.
Advisory locks allow cooperating processes to perform consistent operations on files, but do not guarantee consistency (i.e., processes may still access files without using advisory locks possibly resulting in inconsistencies).
So...
Here's a python program that needs the lock
and unlock
functions on it implemented that will prevent the action from being implemented by more than one thread, in one instance of the process at a time.
(hint: launch with python test.py 1 & python test.py 2 & python test.py 3
)
How would I fix this code so that it works correctly?
import sys
import time
import random
import threading
def lock():
pass # Something here?
def unlock():
pass # Something here?
def action(i):
lock()
id = threading.current_thread()
pid = sys.argv[1]
print("\n")
for i in range(5):
print("--> %s - %s - %s " % (i, id, pid))
unlock()
class Worker(threading.Thread):
def run(self):
for i in range(10):
action(i)
for _ in range(2):
Worker().start()
The current, incorrect output looks like this:
--> 0 - <Worker(Thread-2, started 123145310715904)> - 2
--> 3 - <Worker(Thread-1, started 123145306509312)> - 1
--> 0 - <Worker(Thread-2, started 123145310715904)> - 1
--> 1 - <Worker(Thread-2, started 123145310715904)> - 2
--> 2 - <Worker(Thread-2, started 123145310715904)> - 2
--> 1 - <Worker(Thread-2, started 123145310715904)> - 1
--> 4 - <Worker(Thread-1, started 123145306509312)> - 1
and should look more like:
--> 0 - <Worker(Thread-2, started 123145310715904)> - 1
--> 1 - <Worker(Thread-2, started 123145310715904)> - 1
--> 2 - <Worker(Thread-2, started 123145310715904)> - 1
--> 3 - <Worker(Thread-2, started 123145310715904)> - 1
--> 4 - <Worker(Thread-2, started 123145310715904)> - 1
--> 0 - <Worker(Thread-2, started 123145310715904)> - 2
etc.