The example in this article analyzes Python multithreading usage. Share to everyone for your reference. Specifically as follows:
Today, while learning to try Python multithreading, I suddenly found that I was not very clear about the use of super, so I summed up some of the problems encountered. When I try to write the following code:
Copy Code code as follows:
Class A ():
def __init__ (self):
Print "A"
Class B (A):
def __init__ (self):
Super (B, self). __init__ ()
# a.__init__ (self)
Print "B"
b = B ()
Appear:
Super (B, self). __init__ ()
Typeerror:must is type, not classobj
Finally, it turns out that the problem with the new class in Python is that a must be a new class. The solutions are as follows in two ways:
(1)
Copy Code code as follows:
Class A (object):
def __init__ (self):
Print "A"
Class B (A):
def __init__ (self):
Super (B, self). __init__ ()
# a.__init__ (self) # #这条语句是旧式的, there is a potential problem, you should avoid using
Print "B"
b = B ()
(2)
Copy Code code as follows:
__metaclass__=type
Class A ():
def __init__ (self):
Print "A"
Class B (A):
def __init__ (self):
Super (B, self). __init__ ()
# a.__init__ (self) # #这条语句是旧式的, there is a potential problem, you should avoid using
Print "B"
b = B ()
Attention: If at super (B, self). __init__ ()
Statement to add self, which is super (B, self). __init__ (self), the following error occurs:
Super (B, self). __init__ (self)
TypeError: __init__ () takes exactly 1 argument (2 given)
Above just a little bit of my notes, hehe.
Copy Code code as follows:
Import threading, Time
Class Mythread (threading. Thread):
def __init__ (self, threadname = ""):
#threading. Thread.__init__ (self, name = ThreadName)
Super (Mythread, self). __init__ (name = ThreadName)
def run (self):
Print "starting====", Self.name, Time.ctime ()
Time.sleep (5)
Print "end====", Self.name, Time.ctime (),
m = Mythread ("M")
n = mythread ("n")
M.start ()
N.start ()
Results of output:
starting==== m Mon Aug 08 21:55:41 2011
starting==== n Mon Aug 08 21:55:41 2011
If the main thread of a process finishes running and the child thread is still executing, the process will not exit until all child threads are finished. For example, the following examples:
Copy Code code as follows:
Import threading, Time
Class Mythread (threading. Thread):
def __init__ (self, threadname = ""):
#threading. Thread.__init__ (self, name = ThreadName)
Super (Mythread, self). __init__ (name = ThreadName)
def run (self):
Print "starting====", Self.name, Time.ctime ()
Time.sleep (5)
Print "end====", Self.name, Time.ctime (),
m = Mythread ("M")
M.start ()
Print "Main End"
Print
The results of the output are:
starting==== m Mon Aug 08 22:01:06 2011
Main end
end==== m Mon Aug 08 22:01:11 2011
That is, after the main process is finished, the subprocess is not finished.
If we want the child process to end at the end of the main process, we should use the Setdaemon () function.
Examples are as follows:
Copy Code code as follows:
Import threading, Time
Class Mythread (threading. Thread):
def __init__ (self, threadname = ""):
#threading. Thread.__init__ (self, name = ThreadName)
Super (Mythread, self). __init__ (name = ThreadName)
def run (self):
Print "starting====", Self.name, Time.ctime ()
Time.sleep (5)
Print "end====", Self.name, Time.ctime (),
m = Mythread ("M")
M.setdaemon (True)
M.start ()
Print "Main End"
Print
The result of the output is: Starting====main end m Mon Aug 08 22:02:58 2011
As you can see, the "end=== ..." which should have been printed when the child process m ended was not printed.
Simple thread Synchronization
An execution thread often has to share data, but it's fine to read only shared data, but if multiple threads want to modify shared data, unpredictable results can occur.
If two thread objects T1 and T2 are to add 1 to the numeric num=0, then T1 and T2 will be modified 10 times for NUM, then the final result of Num should be 20. But if T1 gets the value of num (if num is 0 at this point), the system dispatches the T1 to the "sleeping" state, at which point the T2 is converted to the "running" state, at which point the value of num is 0, and then he assigns the T2 value of 1 to Num. The system also converts the T2 into a "sleeping" state, T1 "running" status, and since T1 has got the num value of 0, he also assigns the num+1 value to num 1. Originally 2 times to increase the 1 run, the result is that num only increased 1 times. Situations like this can occur when multithreading is executed concurrently. So in order to prevent this kind of situation, we should use the thread synchronization mechanism.
The simplest synchronization mechanism is "lock"
Lock object with threading. Rlock class Creation
Copy Code code as follows:
Mylock = Threading. Rlock ()
How do I use locks to synchronize threads? The thread can use the acquire () method of the lock so that the lock enters the "locked" state. Only one thread can get a lock at a time. If another thread attempts to acquire the lock, the system becomes "blocked" until the thread that owns the lock invokes the release () method of the lock, so the lock enters the "unlocked" state. The "blocked" state thread receives a notification and has the right to obtain the lock. If more than one thread is in the "blocked" state, all threads will first remove the "blocked" state, and then the system chooses a thread to acquire the lock, and the other threads continue to silence ("blocked").
Copy Code code as follows:
Import threading
Mylock = Threading. Rlock ()
Class Mythread (threading. Thread)
...
def run (self ...):
... #此处 cannot place code to modify shared data
Mylock.acquire ()
... #此处 can place code to modify shared data
Mylock.release ()
... #此处 cannot place code to modify shared data
We refer to code that modifies shared data as a "critical section", which must be closed between the acquire () and the release () method calls of the same lock object.
Locks provide only the most basic level of synchronization. Sometimes more complex thread synchronization is required, such as accessing a critical section only when certain events occur (for example, when a value changes). This requires the use of "conditional variables."
Condition variable with threading. Condition class Creation
Copy Code code as follows:
Mycondition = Threading. Condition ()
How does a conditional variable work? First after a thread succeeds in obtaining a condition variable, the Wait () method that calls this condition variable causes the thread to release the lock and go into the "blocked" state until another thread invokes the Notify () method of the same condition variable to wake the thread that enters the "blocked" state. If you call the Notifyall () method of this condition variable, all the waiting threads will be awakened.
Deadlocks can occur if a program or thread is permanently in the "blocked" state. Therefore, if the use of the lock, condition variables, such as synchronization mechanism, we must pay attention to carefully check to prevent the occurrence of deadlock. For a critical section that might produce an exception, use the finally clause in the exception handling mechanism to guarantee the release of the lock. A thread waiting for a condition variable must be awakened explicitly with the Notify () method, otherwise it will be silent forever. Make sure each wait () method call has a corresponding notify () call, and of course you can call the Notifyall () method just in case.
synchronizing queues
We often use a producer/consumer relationship of two threads to process a shared buffer of data. For example, a producer thread accepts user data into a shared buffer, waiting for a consumer thread to handle the data out. But if the buffer is too small and producer and consumer two asynchronous threads are not at the same speed, it is easy for one thread to wait for another. To minimize the waiting time for the threads that share resources and work at the same speed, we can use a "queue" to provide additional buffers.
To create a queue object, you can use the following code:
Copy Code code as follows:
Import Queue
Myqueue = queue.queue (maxsize = 10)
The Queue.queue class is the synchronous implementation of a queue. The queue length can be unlimited or limited. The queue length can be set by the optional parameter maxsize of the queue's constructor. If the maxsize is less than 1, the queue length is infinite.
Put a value into the queue:
Myqueue.put (10)
The put () method of the calling queue object inserts a project at the end of the team. Put () has two parameters, the first item is required, the value of the inserted item, the second block is an optional parameter, and the default is 1. If the queue is currently empty and the Block-1,put () method suspends the calling thread until a data unit is empty. If the block is a 0,put method, a full exception is thrown.
To remove a value from the queue:
Myqueue.get ()
The Get () method of the calling queue object is deleted from the team header and returns an item. The optional argument is block and the default is 1. If the queue is empty and the Block is 1,get (), the calling thread is paused until a project is available. If the block is 0, the queue throws a empty exception.
Let's use an example to show how to use the queue:
Copy Code code as follows:
# queue_example.py
From queue import queue
Import threading
Import Random
Import time
# Producer Thread
Class Producer (threading. Thread):
def __init__ (self, ThreadName, queue):
Threading. Thread.__init__ (self, name = ThreadName)
Self.sharedata = Queue
def run (self):
For I in range (20):
Print self.getname (), ' adding ', I, ' to queue '
Self.sharedata.put (i)
Time.sleep (Random.randrange (10)/10.0)
Print self.getname (), ' finished '
# Consumer Thread
Class Consumer (threading. Thread):
def __init__ (self, ThreadName, queue):
Threading. Thread.__init__ (self, name = ThreadName)
Self.sharedata = Queue
def run (self):
For I in range (20):
Print self.getname (), ' Got a value: ', Self.sharedata.get ()
Time.sleep (Random.randrange (10)/10.0)
Print self.getname (), ' finished '
# Main Thread
def main ():
Queue = Queue ()
Producer = producer (' producer ', queue)
consumer = consumer (' Consumer ', queue)
print ' Starting threads ... '
Producer.start ()
Consumer.start ()
Producer.join ()
Consumer.join ()
print ' All threads have terminated. '
if __name__ = = ' __main__ ':
Main ()
The result of the program output is:
Starting threads ...
Producer adding 0 to queue
Consumer got a value:0
Producer finished
Producer adding 1 to queue
Producer finished
Producer adding 2 to queue
Consumer finished
Consumer got a value:1
Consumer finished
Consumer got a Value:2
Consumer finished
Consumer got a value:producer finished
Producer adding 3 to queue
3
Consumer finished
Consumer got a value:producer finished
Producer adding 4 to queue
4
Consumerproducer finished
Consumerfinished
Got a value:producer adding 5 to queue
5
Consumer finished
Consumer got a value:producer finished
Producer adding 6 to queue
Producer finished
Producer adding 7 to queue
6
Consumer finished
Consumer got a Value:7
Producer finished
Producer adding 8 to queue
Producer finished
Producer adding 9 to queue
Consumer finished
Consumer got a Value:8
Consumerproducer finishedfinished
Consumerproducer got a value:adding 109
To queue
Producer finished
Producer adding to queue
Producer finished
Producer adding to queue
Consumerproducer finishedfinished
Consumerproducer got a value:adding 1310
To queue
Producer finished
Producer adding to queue
Consumer finished
Consumer got a value:11
Producer finished
Producer adding to queue
Producer finished
Producer adding to queue
Producer finished
Producer adding to queue
Producer finished
Producer adding to queue
Consumer finished
Consumer got a Value:12
Producer finished
Producer adding to queue
Producer finished
Consumer finished
Consumer got a value:13
Consumer finished
Consumer got a value:14
Consumer finished
Consumer got a value:15
Consumer finished
Consumer got a value:16
Consumer finished
Consumer got a value:17
Consumer finished
Consumer got a value:18
Consumer finished
Consumer got a value:19
Consumer finished
All threads have terminated.
I hope this article will help you with your Python programming.