多线程的概念简单多线程的实现和守护进程和全局解释器锁

多线程

系统软件都是通过操作系统(os)去调用cpu进行运算。
每个程序启动会分一块空间,硬盘(自行车)慢,内存(高铁)快,cpu(火箭)还要比内存快好多。cpu有一个时钟频率,代表中断多少次,每中断就能执行一次指令。
每一个程序的内存是独立的
线程————-》一堆指令
操作系统调度cpu最小单位就是线程。线程被包含在进程之中,是进程中一个单一顺序的控制流。一个进程可以并发多个线程,每条线程执行不同的。

进程:一个程序(例如qq)要以一个整体的形式暴露给操作系统管理,里面包含对各种资源的调用,内存的管理,网络接口的调用等。对各种资源管理的集合就可以称为进程。
进程 要操作cpu ,必须先创建一个线程,进程不能执行它是资源的集合。所有在一个同一个进程里的线程是共享同一块内存空间的。

一个cpu只能同时干一件事,但给了你能同时做多个任务的幻觉,因为它进行了上下文的切换,从停止的位置继续做。因为它太速度快了,你切换一次的任务时间能完成n次切换。一个线程就是一堆上下文在寄存器中的组合,线程和进程是不一样的,进程是一堆相关的进行运算的资源的集合,像一个屋子能做多个人和一个人,澄清一下,进程的相关资源包含内存的空间地址,所有在一个同一个进程里的线程是共享同一块内存空间的。

进程,一个程序的执行实例,每一个进程提供执行这个程序所用的所有资源,虚拟的地址空间,可执行的代码,调用的操作系统的接口,安全的权限,唯一的进程标识符(pid),优先级类,最小最大工作所需要的内存空间,至少使用一个线程,当启动一个进程的时候会自动启动一个线程,进程里的第一个线程就是主线程, 子线程是通过主线程创建的,但是子线程是独立的,主线程关闭子线程不会关闭。用各个线程创建子线程。

进程快还是线程快?
没有可比性,进程是资源集合,线程能执行,都是都一样的。
启动进程快还是线程快?
启动一个线程快,启动一个进程相当于修一个屋子,线程像拉个人过来,但是当运行后是一样的,因为进程也是靠线程运行的。
线程共享内存空间,进程是独立的(例qq不能访问word)。

两个线程数据是共享的,而两个子进程是独立的,每创建一个子进程相当于对父进程的克隆,不能互相访问

同一个进程的线程之间可以直接交流,进程是独立的,两个进程想要通信必须通过一个中级代理来实现,创建新线程很简单,创建新进程需要对其父进程进行一次克隆。
一个线程可以控制和操作同一个进程里的其他线程,没有实际的隶属关系,但是进程只能操作子进程。
对于主线程的修改可能影响其他线程的行为(他们是共享数据的),但是对父进程修改不影响子进程。

单线程需要等待两秒

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#  Author: Diedline
import threading
import time
def run(n):
print("test",n)
time.sleep(2)

# T1 = threading.Thread(target=run,args=("t1",))
# #加逗号是因为防止它看做一个参数,因为需要一个元组
# T2 = threading.Thread(target=run,args=("t2",))
# T1.start()
# T2.start()
run("t1")
run("t2")

使用多线程执行不需要等待2s(直接调用方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#  Author: Diedline
import threading
import time
def run(n):
print("test",n)
time.sleep(2)

T1 = threading.Thread(target=run,args=("t1",))
#加逗号是因为防止它看做一个参数,因为需要一个元组
T2 = threading.Thread(target=run,args=("t2",))
T1.start()
T2.start()
# run("t1")
# run("t2")

这就是多线程的魅力

用类的形式启动多线程(继承式调用)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#  Author: Diedline
import threading
import time
class MyThread(threading.Thread):
def __init__(self,n):
super(MyThread,self).__init__()
#继承父类里的__init__
self.n =n
def run(self):
print("run",self.n)


t1 = MyThread("T1")
t2 = MyThread("T2")

t1.start()
t2.start()

主线程启动子线程之后,子线程和主线程就是独立并行的,没有依赖关系。加了join之后主线程依赖子线程执行完毕之后再往下走。

测量总进程所花费时间(50个进程都完成的时间)主线程是程序本身是看不到的,程序退出之前默认有一个join,让所有线程执行完毕。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#  Author: Diedline
import threading
import time
def run(n):
print("test",n)
time.sleep(2)
print("run has done",n)
start_time =time.time()
t_objs = []
for i in range(50):
t = threading.Thread(target=run,args=("t%s"%i,))
t.start()
t_objs.append(t)
for t in t_objs:
t.join()
"""
将t放入数组,然后每执行一次加1让t.join执行50次,实现50个线程都执行结束的效果
(不想卡住下一个进程的启动)
"""

print("cost:",time.time()-start_time)
"""
测出总花费时间
"""

1
print("all thread has finished....",threading.current_thread(),threading.active_count())

threading.current_thread() 可以输出进程的属性(即是主进程还是子进程)
threading.active_count() 输出当前活跃的进程数

例输出
all thread has finished…. <_MainThread(MainThread, started 6704)> 1
有了守护进程之后,只要主线程执行完毕,不管子线程是否执行完毕,就退出了。非守护线程退出了就全部退出了。实际应用场景socket_server没过来一个连接启动一个新线程,如果设置socket server主线程退出就全部停止了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#  Author: Diedline
import threading
import time
def run(n):
print("test",n)
time.sleep(2)
print("run has done",n)
start_time =time.time()
# t_objs = []
for i in range(50):
t = threading.Thread(target=run,args=("t%s"%i,))
t.setDaemon(True) #把当前线程设置为守护线程,一定要在start 之前
t.start()
# t_objs.append(t)
# for t in t_objs:
# t.join()
"""
将t放入数组,然后每执行一次加1让t.join执行50次,实现50个线程都执行结束的效果
(不想卡主下一个进程的启动)
"""

print("cost:",time.time()-start_time)
print("all thread has finished....",threading.current_thread(),threading.active_count())
"""
测出总花费时间
"""

全局解释器锁
cpython 的缺陷
在python 中无论有多少核心都是假象,假的多线程(不停进行上下文切换),python的一个设计缺陷(涉及到线程之间数据共享的问题),其实调用的C语言写的操作系统的原生线程接口。调用它的接口必须知道上下文的关系,所以变成了,python的四个线程确实在4个cpu中,虽然执行只能一个核心上,但是所有执行可能不在同一个核心上,为了避免数据出错python自己加了一个全局锁,同一时间只有一个线程能拿到数据,只有一个线程能实现修改。Java等语言是自己实现的线程,所以没有这种限制。
python的未来pypy:
运行速度特别快,去掉了全局解释器锁只是pypy的一个顺带的功能,主要功能让它变快是加入了一个即时编译器JIT
JIT就是想通过编译技术提升脚本解释器系统的速度。
例如, 被JIT(及时编译)采用的通用方法:
1.标识被经常执行的字节码。
2.把其编译成本地的机器码。
3.缓存该结果。
4.当同样的的字节码再次被执行的时候,会取预编译的机器码,得到好处(例如速度提升)。