A thread is an execution context, which is all the information a CPU needs to execute a stream of instructions.
Suppose you're reading a book, and you want to take a break right now, but you want to be able to come back and resume reading from the exact point where you stopped. One way to achieve that is by jotting down the page number, line number, and
word number. So your execution context for reading a book is these 3 numbers.
If you have a roommate, and she's using the same technique, she can take the book while you're not using it, and resume reading from where she stopped. Then you can take it back, and resume it from where you were.
Threads work in the same way. A CPU is giving you the illusion that it's doing multiple computations at the same time. It does that by spending a bit of time on each computation. It can do that because it has an execution context for each computation.
Just like you can share a book with your friend, many tasks can share a CPU.
On a more technical level, an execution context (therefore a thread) consists of the values of the CPU's registers.
Last: threads are different from processes. A thread is a context of execution, while a process is a bunch of resources associated with a computation. A process can have one or many threads.
Clarification: the resources associated with a process include memory pages (all the threads in a process have the same view of the memory), file descriptors (e.g., open sockets), and security credentials (e.g., the ID of the user who started
the process).
An executing instance of a program is called a process.
Each process provides the resources needed to execute a program. A process has a virtual address space, executable code, open handles to system objects, a security context, a unique process identifier, environment variables, a priority class,
minimum and maximum working set sizes, and at least one thread of execution. Each process is started with a single thread, often called the primary thread, but can create additional threads from any of its threads.
A thread is an execution context, which is all the information a CPU needs to execute a stream of instructions.
Suppose you're reading a book, and you want to take a break right now, but you want to be able to come back and resume reading from the exact point where you stopped. One way to achieve that is by jotting down the page number, line number, and
word number. So your execution context for reading a book is these 3 numbers.
If you have a roommate, and she's using the same technique, she can take the book while you're not using it, and resume reading from where she stopped. Then you can take it back, and resume it from where you were.
Threads work in the same way. A CPU is giving you the illusion that it's doing multiple computations at the same time. It does that by spending a bit of time on each computation. It can do that because it has an execution context for each computation.
Just like you can share a book with your friend, many tasks can share a CPU.
On a more technical level, an execution context (therefore a thread) consists of the values of the CPU's registers.
Last: threads are different from processes. A thread is a context of execution, while a process is a bunch of resources associated with a computation. A process can have one or many threads.
Clarification: the resources associated with a process include memory pages (all the threads in a process have the same view of the memory), file descriptors (e.g., open sockets), and security credentials (e.g., the ID of the user who started
the process).
daemonA boolean value indicating whether this thread isa daemon thread (True) ornot(False). This must be setbefore start() iscalled, otherwise RuntimeError israised. Its initial value isinherited fromthe creating thread; the main thread isnota daemon thread andtherefore allthreads created inthe main thread default to daemon =False.The entire Python program exits when no alive non-daemon threads are left.当daemon被设置为True时,如果主线程退出,那么子线程也将跟着退出,反之,子线程将继续运行,直到正常退出。daemon
CPython implementation detail: In CPython, due to the Global Interpreter Lock, only one thread can execute Python code at once (even though certain performance-oriented libraries might overcome this limitation). If you want your application to
make better use of the computational resources of multi-core machines, you are advised to use multiprocessing. However, threading is still an appropriate model if you want to run multiple I/O-bound tasks simultaneously.
GIL的早期设计
Python支持多线程,而解决多线程之间数据完整性和状态同步的最简单方法自然就是加锁。 于是有了GIL这把超级大锁,而当越来越多的代码库开发者接受了这种设定后,他们开始大量依赖这种特性(即默认python内部对象是thread-safe的,无需在实现时考虑额外的内存锁和同步操作)。慢慢的这种实现方式被发现是蛋疼且低效的。但当大家试图去拆分和去除GIL的时候,发现大量库代码开发者已经重度依赖GIL而非常难以去除了。有多难?做个类比,像MySQL这样的“小项目”为了把Buffer
Pool Mutex这把大锁拆分成各个小锁也花了从5.5到5.6再到5.7多个大版为期近5年的时间,并且仍在继续。MySQL这个背后有公司支持且有固定开发团队的产品走的如此艰难,那又更何况Python这样核心开发和代码贡献者高度社区化的团队呢?
#coding:utf8fromthreading importThreadimporttimedefcounter():i =0for_ inrange(50000000):i =i +1returnTruedefmain():l=[]start_time =time.time()fori inrange(2):t =Thread(target=counter)t.start()l.append(t)t.join()# for t in l:# t.join()end_time =time.time()print("Total time: {}".format(end_time -start_time))if__name__ =='__main__':main()'''py2.7:串行:25.4523348808s并发:31.4084379673spy3.5:串行:8.62115597724914s并发:8.99609899520874s'''
多进程
多进程的概念
multiprocessing is a package that supports spawning processes using an API similar
to the threading module. The multiprocessing package offers both local and remote concurrency,effectively side-stepping the Global Interpreter Lock by
using subprocesses instead of threads. Due to this, the multiprocessing module
allows the programmer to fully leverage multiple processors on a given machine. It runs on both Unix and Windows.
importtimefrommultiprocessing importProcessdeffoo(i):time.sleep(1)print(p.is_alive(),i,p.pid)time.sleep(1)if__name__ =='__main__':p_list=[]fori inrange(10):p =Process(target=foo, args=(i,))#p.daemon=Truep_list.append(p)forp inp_list:p.start()# for p in p_list:# p.join()print('main process end')