Lock
Python's built-in data structures such as lists and dictionaries are thread-safe, but simple data types such as integers and floating-point numbers are not thread-safe, and for those simple data types to operate, locks are required.
#!/usr/bin/env Python3 # coding=utf-8 import Threading Shared_resource_with_lock = 0 Shared_resource_with_no_lock = 0 C Ount = 100000 Shared_resource_lock = Threading. Lock () ### #LOCK management## def increment_with_lock (): Global shared_resource_with_lock for I in Range (COUNT): s Hared_resource_lock.acquire () Shared_resource_with_lock = 1 shared_resource_lock.release () def Decrement_wit H_lock (): Global shared_resource_with_lock for I in Range (COUNT): Shared_resource_lock.acquire () shared_resour Ce_with_lock-= 1 shared_resource_lock.release () ### #NO lock MANAGEMENT # def increment_without_lock (): Glob Al Shared_resource_with_no_lock for I in Range (COUNT): Shared_resource_with_no_lock + 1 def decrement_without_lo CK (): Global shared_resource_with_no_lock for I in Range (COUNT): Shared_resource_with_no_lock-= 1 ### #the Main program if __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 Oin () T4.join () print ("The value of shared variable with lock management is%s" \%shared_resource_with_lock) prin
T ("The value of shared variable with race condition is%s" \%shared_resource_with_no_lock)
Execution results:
$./threading_lock.py
The value of shared variable with lock management was 0 the
value of shared variable with race condition is 0
Another example:
Import random import Threading Import Time Logging.basicconfig (level=logging. DEBUG, format= ' (% (threadname) -10s)% (message) s ', "Class Counter (object): Def __init__ (SE LF, 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 ()) ) Logging.debug (' acquired lock ') Self.value = self.value + 1 logging.debug (' lock {0} seconds '. Form at (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 () to I in range (2): T = Threading. Thread (Target=worker, args= (counter,)) T.staRT () Logging.debug (' Waiting for worker threads ') Main_thread = Threading.currentthread () to T in Threading.enumerate ():
If T is not main_thread:t.join () logging.debug (' Counter:%d ', counter.value)
Execution results:
$ python threading_lock.py
(Thread-1) Tue Sep 15:49:18 2015 (Thread-1) Sleeping 3.00 (Thread-2) Tue Sep 15:49:18 2015 (mainthread) waiting for worker th Reads (Thread-2) sleeping 2.00 (Thread-2) Tue Sep 15:49:20 2015 (Thread-2) waiting for Lock (Thread-2) Tue Sep 15 1 5:49:20 2015 (THREAD-2) acquired lock (Thread-2) lock 2 seconds (Thread-1) Tue Sep 15:49:21 2015 (Thread-1) waiting For lock (Thread-2) Tue Sep 15:49:22 2015 (Thread-1) Tue Sep 15:49:22 2015 (Thread-2) sleeping 2.00 (Thread-1) Acquired lock (Thread-1) lock 1 seconds (Thread-1) Tue Sep 15:49:23 2015 (Thread-1) sleeping 2.00 (Thread-2) Tue Se P 15:49:24 2015 (Thread-2) waiting for Lock (Thread-2) Tue Sep 15:49:24 2015 (Thread-2) acquired lock (Thread-2) Lock 1 seconds (Thread-1) Tue Sep 15:49:25 2015 (Thread-1) waiting for Lock (Thread-1) Tue Sep 15:49:25 2015 (Th
READ-1) acquired lock (Thread-1) lock 2 seconds (Thread-2) do (Thread-1) done (mainthread) counter:4
Acquire () to pass the value of false to check for a lock. For example,
Import Logging import Threading Import Time Logging.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.D Ebug (' starting ') num_tries = 0 Num_acquires = 0 while num_acquires < 3:time.sleep (0.5) logging.debug (' Tr Ying to acquire ') Have_it = Lock.acquire (0) Try:num_tries + + 1 if have_it:logging.debug (' Ite Ration%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 afte R%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 results:
$ 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 ) after 5 iterations
Line Cheng Ann full lock
Returns a lock object that can be reentrant. The reentrant lock must be freed by the thread that obtained it. Once the thread acquires a reentrant lock, the same path is obtained again without blocking, and must be released after the acquisition.
Usually one thread can get only one lock at a time:
Import Threading
Lock = Threading. Lock ()
print ' A: ', Lock.acquire ()
print ' Second try: ', Lock.acquire (0)
Execution results:
$ python threading_lock_reacquire.py
Try:true
Second Try:false
Use Rlock to obtain multiple locks:
Import Threading
Lock = Threading. Rlock ()
print ' A: ', Lock.acquire ()
print ' Second try: ', Lock.acquire (0)
Execution results:
Python threading_rlock.py
Let's look at one more example:
#!/usr/bin/env Python3 # Coding=utf-8 Import Threading Import Time Class 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 Remov
E (self): Box.lock.acquire () Self.execute ( -1) Box.lock.release () # # This 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 (" Removin G 1 Item in the box ") Box.remove () Time.sleep (5) Items-= 1 # # The main program build some # threads and
Make sure it works if __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 results:
$ Python3 threading_rlock2.py
Putting 5 items in the box
adding 1 item in the box
removing 1 item in the box
adding 1 item in the box
re Moving 1 item in the box
adding 1 item in the box
removing 1 item in the box
removing 1 item in the box
a Dding 1 item in the box
removing 1 item in the box
adding 1 item in the box
0 items still remain in the box