For example, the use of thread locks in Python programming and python Programming
Lock
Python's built-in data structures, such as lists and dictionaries, are thread-safe. However, simple data types, such as integers and floating-point numbers, are not thread-safe. You need to perform operations on these simple data types, you need to use the lock.
#!/usr/bin/env python3# coding=utf-8import threadingshared_resource_with_lock = 0shared_resource_with_no_lock = 0COUNT = 100000shared_resource_lock = threading.Lock()####LOCK MANAGEMENT##def increment_with_lock(): global shared_resource_with_lock for i in range(COUNT): shared_resource_lock.acquire() shared_resource_with_lock += 1 shared_resource_lock.release() def decrement_with_lock(): global shared_resource_with_lock for i in range(COUNT): shared_resource_lock.acquire() shared_resource_with_lock -= 1 shared_resource_lock.release() ####NO LOCK MANAGEMENT ## def increment_without_lock(): global shared_resource_with_no_lock for i in range(COUNT): shared_resource_with_no_lock += 1 def decrement_without_lock(): global shared_resource_with_no_lock for i in range(COUNT): shared_resource_with_no_lock -= 1 ####the Main programif __name__ == "__main__": t1 = threading.Thread(target = increment_with_lock) t2 = threading.Thread(target = decrement_with_lock) t3 = threading.Thread(target = increment_without_lock) t4 = threading.Thread(target = decrement_without_lock) t1.start() t2.start() t3.start() t4.start() t1.join() t2.join() t3.join() t4.join() print ("the value of shared variable with lock management is %s"\ %shared_resource_with_lock) print ("the value of shared variable with race condition is %s"\ %shared_resource_with_no_lock)
Execution result:
$ ./threading_lock.py
the value of shared variable with lock management is 0the value of shared variable with race condition is 0
Another example:
import randomimport threadingimport timelogging.basicConfig(level=logging.DEBUG, format='(%(threadName)-10s) %(message)s', ) class Counter(object): def __init__(self, start=0): self.lock = threading.Lock() self.value = start def increment(self): logging.debug(time.ctime(time.time())) logging.debug('Waiting for lock') self.lock.acquire() try: pause = random.randint(1,3) logging.debug(time.ctime(time.time())) logging.debug('Acquired lock') self.value = self.value + 1 logging.debug('lock {0} seconds'.format(pause)) time.sleep(pause) finally: self.lock.release()def worker(c): for i in range(2): pause = random.randint(1,3) logging.debug(time.ctime(time.time())) logging.debug('Sleeping %0.02f', pause) time.sleep(pause) c.increment() logging.debug('Done')counter = Counter()for i in range(2): t = threading.Thread(target=worker, args=(counter,)) t.start()logging.debug('Waiting for worker threads')main_thread = threading.currentThread()for t in threading.enumerate(): if t is not main_thread: t.join()logging.debug('Counter: %d', counter.value)
Execution result:
$ python threading_lock.py
(Thread-1 ) Tue Sep 15 15:49:18 2015(Thread-1 ) Sleeping 3.00(Thread-2 ) Tue Sep 15 15:49:18 2015(MainThread) Waiting for worker threads(Thread-2 ) Sleeping 2.00(Thread-2 ) Tue Sep 15 15:49:20 2015(Thread-2 ) Waiting for lock(Thread-2 ) Tue Sep 15 15:49:20 2015(Thread-2 ) Acquired lock(Thread-2 ) lock 2 seconds(Thread-1 ) Tue Sep 15 15:49:21 2015(Thread-1 ) Waiting for lock(Thread-2 ) Tue Sep 15 15:49:22 2015(Thread-1 ) Tue Sep 15 15:49:22 2015(Thread-2 ) Sleeping 2.00(Thread-1 ) Acquired lock(Thread-1 ) lock 1 seconds(Thread-1 ) Tue Sep 15 15:49:23 2015(Thread-1 ) Sleeping 2.00(Thread-2 ) Tue Sep 15 15:49:24 2015(Thread-2 ) Waiting for lock(Thread-2 ) Tue Sep 15 15:49:24 2015(Thread-2 ) Acquired lock(Thread-2 ) lock 1 seconds(Thread-1 ) Tue Sep 15 15:49:25 2015(Thread-1 ) Waiting for lock(Thread-1 ) Tue Sep 15 15:49:25 2015(Thread-1 ) Acquired lock(Thread-1 ) lock 2 seconds(Thread-2 ) Done(Thread-1 ) Done(MainThread) Counter: 4
In acquire (), pass in the False value to check whether the lock is obtained. For example:
import loggingimport threadingimport timelogging.basicConfig(level=logging.DEBUG, format='(%(threadName)-10s) %(message)s', ) def lock_holder(lock): logging.debug('Starting') while True: lock.acquire() try: logging.debug('Holding') time.sleep(0.5) finally: logging.debug('Not holding') lock.release() time.sleep(0.5) return def worker(lock): logging.debug('Starting') num_tries = 0 num_acquires = 0 while num_acquires < 3: time.sleep(0.5) logging.debug('Trying to acquire') have_it = lock.acquire(0) try: num_tries += 1 if have_it: logging.debug('Iteration %d: Acquired', num_tries) num_acquires += 1 else: logging.debug('Iteration %d: Not acquired', num_tries) finally: if have_it: lock.release() logging.debug('Done after %d iterations', num_tries)lock = threading.Lock()holder = threading.Thread(target=lock_holder, args=(lock,), name='LockHolder')holder.setDaemon(True)holder.start()worker = threading.Thread(target=worker, args=(lock,), name='Worker')worker.start()
Execution result:
$ python threading_lock_noblock.py
(LockHolder) Starting(LockHolder) Holding(Worker ) Starting(LockHolder) Not holding(Worker ) Trying to acquire(Worker ) Iteration 1: Acquired(LockHolder) Holding(Worker ) Trying to acquire(Worker ) Iteration 2: Not acquired(LockHolder) Not holding(Worker ) Trying to acquire(Worker ) Iteration 3: Acquired(LockHolder) Holding(Worker ) Trying to acquire(Worker ) Iteration 4: Not acquired(LockHolder) Not holding(Worker ) Trying to acquire(Worker ) Iteration 5: Acquired(Worker ) Done after 5 iterations
Thread security lock
threading.RLock()
Returns the reentrant Lock Object. The re-entry lock must be released by the thread that obtains it. Once the thread gets the re-entry lock, the same thread can obtain the lock again without blocking. After obtaining the lock, it must be released.
Generally, a thread can only obtain a lock once:
import threadinglock = threading.Lock()print 'First try :', lock.acquire()print 'Second try:', lock.acquire(0)
Execution result:
$ python threading_lock_reacquire.py
First try : TrueSecond try: False
You can use RLock to obtain multiple locks:
import threadinglock = threading.RLock()print 'First try :', lock.acquire()print 'Second try:', lock.acquire(0)
Execution result:
python threading_rlock.py
First try : TrueSecond try: 1
Let's look at an example:
#!/usr/bin/env python3# coding=utf-8import threadingimport timeclass Box(object): lock = threading.RLock() def __init__(self): self.total_items = 0 def execute(self,n): Box.lock.acquire() self.total_items += n Box.lock.release() def add(self): Box.lock.acquire() self.execute(1) Box.lock.release() def remove(self): Box.lock.acquire() self.execute(-1) Box.lock.release() ## These two functions run n in separate## threads and call the Box's methods def adder(box,items): while items > 0: print ("adding 1 item in the box\n") box.add() time.sleep(5) items -= 1 def remover(box,items): while items > 0: print ("removing 1 item in the box") box.remove() time.sleep(5) items -= 1 ## the main program build some## threads and make sure it worksif __name__ == "__main__": items = 5 print ("putting %s items in the box " % items) box = Box() t1 = threading.Thread(target=adder,args=(box,items)) t2 = threading.Thread(target=remover,args=(box,items)) t1.start() t2.start() t1.join() t2.join() print ("%s items still remain in the box " % box.total_items)
Execution result:
$ python3 threading_rlock2.py
putting 5 items in the box adding 1 item in the boxremoving 1 item in the boxadding 1 item in the boxremoving 1 item in the boxadding 1 item in the boxremoving 1 item in the boxremoving 1 item in the boxadding 1 item in the boxremoving 1 item in the boxadding 1 item in the box0 items still remain in the box