一、线程与进程的介绍参考之前写的VC++的多线程与互斥对象:
https://blog.csdn.net/Gordennizaicunzai/article/details/52268343
二、python全局解析器锁(GIL)。
python代码相对于其它语言在多线程效率上有个“先天性缺陷”——python有个虚拟机(又名解析器主循环)对代码进行执行控制,在解析器主循环中单位时间内只能有一个控制线在执行。意思是任意时刻只能有一个程序在运行,即使内存中有多个程序。python通过GIL对虚拟机进行访问:
1、设置GIL。
2、切换进一个线程去运行。
3、执行下面操作之一:
a. 指定数量的字节码指令。
b. 线程主动让出控制权(可以调用time.sleep(0))来完成。
4、把线程设置回睡眠状态(切换退出线程)。
5、解锁GIL。
6、重复1~5。
对效率要求非常高的python开发中,倾向于这样设计:
IO密集型(不用CPU)——多线程
计算密集型(用CPU)——多进程
三、Threading模块的对象。
对象 | 描述 |
Thread | 表示一个执行线程的对象。 |
Lock | 锁原语对象(和thread模块中的锁一样)。 |
Rlock | 可重入锁对象,使单一线程可以(再次)获得已持有的锁(递归锁)。 |
Condition | 条件变量对象,使得一个线程等待另一个线程满足特定的“条件”,比如改变状态或某个数据值。 |
Event | 条件变量的通用版本,任意数量的线程等待某个事件的发生,在该事件发生后所有线程将被激活。 |
Semaphore | 为线程间共享的有限资源提供了一个“计数器”,如果没有可用资源时会被阻塞。 |
BoundedSemaphore | 与Semahore相似,不过它不允许超过初始值。 |
Timer | 与Thread相似,不过它要在运行前等待一段时间。 |
Barrier | 创建一个“障碍”,必须达到指定数量的线程后才可以继续。 |
3.1、Thread类。
属性或方法 | 描述 |
name | 线程名,可以用直接赋值进行修改,如Thread.name = 'T1'。 |
ident | 线程的标识符。 |
daemon | 布尔标志,True为守护线程,False则不是,可以直接赋值,如Thread.daemon = True。 |
_init_(group=None, tatget=None, name=None, args=(), kwargs={}, verbose=None, daemon=None) |
实例化一个线程对象,需要有一个可调用的target,以及其参数args(传元祖等iterable)或kwargs。还可以传递name或group参数,不过后者还未实现。此外,verbose标志也是可以接受的。而daemon的值将会设定thread.daemon属性/标志。 |
start() | 开始执行该线程。 |
run() | 定义线程功能的方法(通常在子类中被应用开发者重写)。 |
join(timeout=None) | 直至启动的线程终止之前一直挂起:除非给出了timeout(秒),否则会一直阻塞。自旋锁。 |
is_alive() | 布尔标志,表示这个线程是否还活着。 |
>>> import threading
>>> import time
>>>
>>> def thread1(tickets):
if tickets <= 0:
print("输入的票数不能小于等于0")
return False
while tickets > 0:
print("thread1 sell ticket : %d" % tickets)
tickets -= 1
time.sleep(1)
return True
>>> t1 = threading.Thread(target=thread1,args=(50,))
>>> t1
<Thread(Thread-4, initial)>
>>> t1.name
'Thread-4'
>>> t1.name = 'T1'
>>> t1
<Thread(T1, initial)>
>>> t1.name
'T1'
>>> t1.daemon
False
>>> t1.daemon = True
>>> t1.daemon
True
>>> t1.is_alive()
False