The difference between 9.94 and daemon daemon thread
1. for the main process, the operation is completed refers to the main process code has finished running
2 to the main thread, the run is completed refers to all non-daemon threads within a process where all the main thread has finished running, considered the main thread running complete detailed explanation: 1. the main process after the end of its code has finished running the count (daemon was recovered at this point), then the process will always wait for the main guardian of the child process after a non-finish run sub-process recycling resources (otherwise it will produce zombie process), will end, 2. considered the main thread has finished running (daemon thread is recovered at this time) after other non-daemon thread has finished running. Since the end of the end of the process means that the main thread, the whole process will be recycled resources, and the process must be guaranteed to end after non-daemon threads have finished running.
9.95 thread mutex
from threading import Thread,Lock import time mutex=Lock() x=100 def task(): global x mutex.acquire() temp=x time.sleep(0.1) x=temp-1 mutex.release() if __name__ == '__main__': start=time.time() t_l=[] for i in range(100): t=Thread(target=task) t_l.append(t) t.start() for t in t_l: t.join() print('主',x) #主 0 print(time.time()-start) #10.1311
9.96 deadlock with recursive lock
mutexA = mutexB = RLock () to get a thread lock, counter plus 1, in this thread ran into a locked case, the counter continues to add 1, during which all the other threads can only wait, wait for the thread to release all locks that the counter is decremented until 0
from Threading Import the Thread, Lock, RLOCK Import Time # mutexA = Lock () # mutexB = Lock () # deadlock mutexA = mutexB = RLOCK () # recursive lock class the MyThread (the Thread): DEF RUN (Self): Self. F1 () self.f2 () DEF F1 (Self): mutexA.acquire () Print ( ' % S got a lock ' % the self.name) mutexB.acquire () Print ( ' % S B got a lock ' % self.name) mutexB.release () mutexA.release () def f2(self): mutexB.acquire() print('%s 拿到了B锁' %self.name) time.sleep(0.1) mutexA.acquire() print('%s 拿到了A锁' %self.name) mutexA.release() mutexB.release() if __name__ == '__main__': for i in range(10): t=MyThread() t.start() Print ( 'Main ' )
9.97 semaphore
Like the process, Semaphore management of a built-in counter, every time we call acquire () built-in counter -1; call release built-in counter + 1 (when); counter can not be less than zero; when the counter is 0, acquire () will block thread until another thread invokes the release ()
# from multiprocessing import Semaphore from threading import Thread,Semaphore,current_thread import time,random sm=Semaphore(5) def go_wc(): sm.acquire() print('%s 上厕所ing' %current_thread().getName()) time.sleep(random.randint(1,3)) sm.release() if __name__ == '__main__': for i in range(23): t=Thread(target=go_wc) t.start()
Pool and process are completely different concepts, process pool Pool (4), the maximum can only produce 4 process, and the process from start to finish just four, no new, and semaphores is to generate a bunch of threads / process
GIL: Global Interpreter Lock GIL is essentially a mutex, is caught in the body of the interpreter, each within a python process has such a lock, all threads within the same process will need to grab the GIL lock, to perform interpreter code
What kind of impact will GIL multiple threads in a single process resulting in: multi-thread execution order, you first need to scramble GIL, for all threads to be executed for, GIL is equivalent to execute permissions, that only one thread contention grab success, that is, multiple threads at the same time only a single process running multiple threads in a single process means that there is no parallel effect, but the effect of concurrent
ps: disperse in different threads within the same process will not go to compete for the GIL, only with multiple threads of a process before the competition for the same GIL
Why should GIL: memory management Cpython interpreter is not thread safe
GIL advantages and disadvantages: Advantages: thread-safe Cpython interpreter memory management
Disadvantages: within the same process all of the threads in the same moment, only one execution, also said that multi-threaded Cpython interpreter can not be achieved in parallel
GIL with a custom mutex similarities and differences , a plurality of threads with a custom competition GIL mutex process analysis: same: mutexes are different: GIL is applied to the interpreter, the global effect, since mutex to define the role of the local; all threads within a single process to grab GIL, only a portion of threads within a single process will try to steal from the definition of mutex
9.101 Cpython interpreter concurrent verify efficiency
Multiple threads in a single process can not be parallel, not parallel means you can not use the advantages of multi-core
You should use multiple compute-intensive processes, such as financial analysis; IO intensive use should be multi-threaded, multi-check negligible performance improvements, such as socket, reptiles, web
9.102 thread and mutex contrast GIL
GIL protection is to explain the stages of data, to protect the user's own data you need to own the lock processing
from Threading Import the Thread, Lock Import Time mutex = Lock () COUNT = 0 DEF Task (): , Ltd. Free Join COUNT mutex.acquire () # GIL only allow threads to access to the interpreter code that is executed to get permission, then target code to the interpreter substituting TEMP = COUNT # code to execute, but can not get the mutex thread, similarly to wait the time.sleep (0.1 ) COUNT = TEMP +. 1 mutex.release () IF the __name__ == ' __main__ ' : T_L = [] for I in range(2): t=Thread(target=task) t_l.append(t) t.start() for t in t_l: t.join() print('主',count) #主 2