This article introduces several examples of the differences between daemon attribute values in Python multi-threading.
Review:
The previous article briefly describes the modern operating system in which each process considers itself exclusive of all computer resources.
Or the thread is the independent kingdom, the process is relatively independent, can not casually share data.
A thread is a province, and a thread within the same process can share the resources of a process, each with its own stack.
- Each process must have at least one thread, and the most procedural entry, and this process is the main thread.
- Each process must have at least one main thread, and other threads are called worker threads.
- Parent thread: If thread A initiates a thread, B,a is the parent thread of B.
- Child Thread: B is a sub-thread
In Python, when you construct a thread object, you can set the Daemon property, which must be set before the Start method.
The main thread is the first one that is started by the program, and the main thread can then start n child threads.
The Daemon property can not be set, the default is None, and the main thread defaults to False.
See how a daemon attribute is designed in the source code:
class Thread:
def __init __ (self, group = None, target = None, name = None,
args = (), kwargs = None, *, daemon = None): #daemon attribute value is None by default
if daemon is not None:
self._daemonic = daemon
else:
self._daemonic = current_thread (). daemon
After reading the following examples, you will understand the meaning of the source code.
The daemon attribute values are divided into the following three types:
1) Daemon=false
When Daemon is false, the parent thread waits for all child threads to exit before ending the program after it finishes running.
Example:
import threading
import time
def foo ():
for i in range (3):
print (‘i = (}, foo thread daemon is (}‘. format (i, threading.current_thread (). isDaemon ()))
time.sleep (1)
t = threading.Thread (target = foo, daemon = False)
t.start ()
print ("Main thread daemon is {}". format (threading.current_thread (). isDaemon ()))
print ("Main Thread Exit.")
operation result:
i = 0, foo thread daemon is False
Main thread daemon is False
Main Thread Exit.
i = 1, foo thread daemon is False
i = 2, foo thread daemon is False
The Isdaemon () method allows you to return the daemon value of the current thread, the default is False, and the child thread is false because Daemon=false is specified when the thread object is created.
According to the order of the results of the operation can be learned that the main program after the thread object is immediately started, and then the child thread returned the results of the first line of content, and then sleep 1 seconds to simulate IO, when the CPU found that the child thread blocked, immediately cut to the main thread to continue execution, the main thread successively print the second and third rows The code for the main thread is now executed to the end. Then, because the main thread sets the Daemon=false property for the child thread, then the thread switches to the child thread, the child thread executes line fourth and line fifth, then the child thread executes completely, and the main thread sees that the child thread exits and exits immediately, and the whole program ends.
2) Daemon=true
When Daemon is true, when the parent thread finishes running, the child thread exits with the main thread, whether or not it is running.
Example:
import threading
import time
def foo ():
for i in range (3):
print (‘i = (}, foo thread daemon is (}‘. format (i, threading.current_thread (). isDaemon ()))
time.sleep (1)
t = threading.Thread (target = foo, daemon = True)
t.start ()
print ("Main thread daemon is {}". format (threading.current_thread (). isDaemon ()))
print ("Main Thread Exit.")
operation result :
i = 0, foo thread daemon is True
Main thread daemon is False
Main Thread Exit.
From the running result, when the child thread sets the Daemon property to True, that is, the main thread does not care about the child thread running state, the main thread exits, and the child thread must follow the exit.
So the result of the operation of the neutron thread only executed a sentence, on the main thread, the main thread executes the last two sentences, immediately exit, the entire program ends.
3) not set, or Daemon=none
The Daemon property can be set without a default value of None.
Example:
import threading
import time
def bar ():
while True: # child loop of infinite loop
print (‘[bar] daemon is {}’. format (threading.current_thread (). isDaemon ()))
time.sleep (1)
def foo ():
for i in range (3): #Start 3 child threads
print (‘i = {}, [foo] thread daemon is {}‘. format (i, threading.current_thread (). isDaemon ()))
t1 = threading.Thread (target = bar, daemon = None)
t1.start ()
t = threading.Thread (target = foo, daemon = True)
t.start ()
print ("Main thread daemon is {}". format (threading.current_thread (). isDaemon ()))
time.sleep (2)
print ("Main Thread Exit.")
operation result:
i = 0, [foo] thread daemon is True
Main thread daemon is False
[Bar] daemon is True
i = 1, [foo] thread daemon is True
[Bar] daemon is True
i = 2, [foo] thread daemon is True
[Bar] daemon is True
[Bar] daemon is True
[Bar] daemon is True
[Bar] daemon is True
Main Thread Exit.
This is used in the main thread for a delay of 2 seconds, to let the child thread initiated by the child thread has the opportunity to output its Daemon property value, if not set the delay, because the child thread set daemon=ture, double thread daemon to none is equivalent to fetching the parent thread's daemon value ( The parent thread of the double thread is the child thread, and the child thread daemon=true), so the while Infinite loop in the final child child thread is forcibly exited by its parent thread (child thread).
Look at the case where the daemon of the child thread is false, respectively:
import threading
import time
def bar ():
while True: # child loop of infinite loop
print (‘[bar] daemon is {}’. format (threading.current_thread (). isDaemon ()))
time.sleep (1)
def foo ():
for i in range (3): #Start 3 child threads
print (‘i = {}, [foo] thread daemon is {}‘. format (i, threading.current_thread (). isDaemon ()))
t1 = threading.Thread (target = bar, daemon = False)
t1.start ()
t = threading.Thread (target = foo, daemon = True)
t.start ()
print ("Main thread daemon is {}". format (threading.current_thread (). isDaemon ()))
time.sleep (2)
print ("Main Thread Exit.")
operation result:
i = 0, [foo] thread daemon is True
Main thread daemon is False
[Bar] daemon is False
i = 1, [foo] thread daemon is True
[Bar] daemon is False
i = 2, [foo] thread daemon is True
[Bar] daemon is False
[Bar] daemon is False
[Bar] daemon is False
[Bar] daemon is False
Main Thread Exit.
[Bar] daemon is False
[Bar] daemon is False
[Bar] daemon is False
[Bar] daemon is False
[Bar] daemon is False
[Bar] daemon is False
[Bar] daemon is False
[Bar] daemon is False
[Bar] daemon is False
[Bar] daemon is False
[Bar] daemon is False
.......Infinite loop....
The main thread would have been unequal to the execution of the child thread, but the child thread would wait for the double thread to complete, and the double thread would be an infinite loop. So eventually the main thread can not stop the child thread has been crazy output, this is like Grandpa Tube got son, but can't control grandson Ah.
At the end of this example, the second line of sleep (2) is run in the main thread, and if you comment out the statement, you will see that the result is:
I=0, "foo" thread daemon is truemain thread daemon is falsemain thread Exit.
Although the child thread runs, but before it can start the child sub-thread, the main thread executes to the last, and ends the program directly.
If that scares the double thread to start up one, the main thread is out of the way, this guy's crazy output.
So if there is no sleep (2) This statement, you will not see the real effect.
Summarize:
Now look at the daemon attribute in the thread class of the source code, it can be understood.
class Thread:
def __init __ (self, group = None, target = None, name = None,
args = (), kwargs = None, *, daemon = None): #daemon attribute value is None by default
if daemon is not None:
self._daemonic = daemon
else:
self._daemonic = current_thread (). daemon
The approximate logic is as follows:
Passing in the Daemon property value when creating a thread object
If the value is not none, which means that the pass is true or false, of course, this is assumed, in case there is a perversion of the value of the mess, but the interpreter will be thrown at runtime is absolutely abnormal.
The value passed in is the daemon value that is the target thread.
If no value is passed in, or if Daemon=none is passed in, it is equivalent to None, and the value of the target thread takes the parent thread's daemon value as its own daemon value.
That is to point out the source of Current_thread () is which thread, in the third example, the child thread is created in the child thread object, so Current_thread () This current thread is a child thread, double thread does not pass in the Daemon property value, Therefore, the Daemon property value of the thread is created as the Daemon property value of the child thread.
Considering such a scenario, the main thread only initiates the child thread, the Cheng thread, and the child thread does not set the Daemon property, that is, who created the thread (which is, of course, created by the main thread), and takes its daemon attribute value as the daemon value of the thread. The default daemon value of the main thread is false, so this child thread will eventually pass in false.
So:
import threading
import time
def foo ():
for i in range (3):
print (‘i = {}, [foo] thread daemon is {}‘. format (i, threading.current_thread (). isDaemon ()))
time.sleep (1)
t = threading.Thread (target = foo)
t.start ()
print ("Main thread daemon is {}". format (threading.current_thread (). isDaemon ()))
# time.sleep (2)
print ("Main Thread Exit.")
operation result:
i = 0, [foo] thread daemon is False
Main thread daemon is False
Main Thread Exit.
i = 1, [foo] thread daemon is False
i = 2, [foo] thread daemon is False
Child thread Daemon=false.
.
[Python Multithreading] Detailed daemon attribute value None,false,true difference (v)