发展背景
任务调度
大部分操作系统都是轮流执行任务.
因为cpu发展快,程序进行快看起来就像同时运行,称作并发.
进程
进程
是一个具有一定独立功能的程序在一个数据集上的一次动态执行的过程,是操作系统进行资源分配和调度的一个独立单位,是应用程序运行的载体.
一般由程序
、数据集合
和进程控制块
三部分组成。程序用于描述进程要完成的功能,是控制进程执行的指令集;数据集合是程序在执行时所需要的数据和工作区;程序控制块(Program Control Block,简称PCB),包含进程的描述信息和控制信息,是进程存在的唯一标志。
线程
早期的操作系统中并没有线程的概念,进程是能拥有资源和独立运行的最小单位,也是程序执行的最小单位。任务调度采用的是时间片轮转的抢占调度方式,而进程是任务调度的最小单位,每个进程都有各自独立的一块内存,使得各个进程之间内存地址相互隔离。
后来,计算机发展对CPU要求提高,进程间切换开销大,无法满足越来越复杂的程序要求,于是有了线程.
线程
是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位。
一个进程可以由一个或者多个线程,各个线程之间共享的内存空间(即所在进程的内存空间)。一个标准的线程由线程ID、当前指令指针(PC)、寄存器和堆栈组成。而进程由内存空间(代码、数据、进程空间、打开的文件)和一个获多个线程组成。
进程与线程区别
- 线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位;
- 一个进程由一个获多个线程组成,线程是一个进程中代码的不同执行路线;
- 进程之间相互独立,同一进程下的各个线程之间共享程序的内存空间及一些进程级的资源,某进程内的线程在其它进程不可见;
- 调度和切换:线程上下文切换比进程上下文切换快得多.
Python多线程
其实只有单线程,是伪多线程
- thread模块
- threading模块(推荐使用)
thread
不支持守护线程。当主线程退出时,所有的子线程不管是否在工作,都会被强制退出。有时我们不希望这样,就有了threading
模块支持守护线程。
import time
import threading
# 单线程
'''
def music(name, loop):
for i in range(loop):
print('listen music %s %s' % (name, time.ctime))
time.sleep(1)
def movie(name, loop):
for i in range(loop):
print('lool movie %s %s' % (name, time.ctime))
time.sleep(1)
if __name__ == '__main__':
music('爱的故事',3)
movie('肖申克的救赎',4)
print('end time %s'%time.ctime)
'''
# 多线程
def music(name, loop):
for i in range(loop):
print('listen music %s %s %s' % (name, time.ctime(),threading.Thread.getName(t1)))
time.sleep(1)
def movie(name, loop):
for i in range(loop):
print('lool movie %s %s %s' % (name, time.ctime(),threading.Thread.getName(t2)))
time.sleep(1)
# 1.创建多线程
t1 = threading.Thread(target=music,args=('爱的故事',3))
t1.setName('musicThread')
t2 = threading.Thread(target=movie,args=('肖申克的救赎',4))
t2.setName('movieThread')
if __name__ == '__main__':
# music('爱的故事',3)
# movie('肖申克的救赎',4)
# 4.守护主线程,主线程结束杀死子线程
t1.setDaemon(True)
t2.setDaemon(True)
# 2.启动线程
t1.start()
t2.start()
print('end time %s'%time.ctime())
print(t1.ident)
print(t2.ident)
# 3.join可以对主线程进行阻塞,所有的子线程运行结束再运行主线程
t1.join()
t2.join()
print('主线程:%s'%time.ctime())
Python多进程
-
用multiprocessing替代Thread
-
multiprcoessing库的出现很大程度时为了弥补thread库因为GIL低效的缺陷。它完整的复制了一套thread所提供的接口方便迁移。唯一的不同是它使用了多进程而不是多线程。每个进程有自己的独立的GIL,完全并行,无GIL的限制(进程中包括线程),可充分利用多cpu多核的环境,因此也不会出现进程之间的GIL争抢。
'''
# 单进程
import time
def work_1(f,n):
print('work_1 start')
for i in range(n):
with open(f,'a') as fs:
fs.write('i love python\n')
time.sleep(1)
print('work_1 end')
def work_2(f,n):
print('work_2 start')
for i in range(n):
with open(f,'a') as fs:
fs.write('come on baby \n')
time.sleep(1)
print('work_2 end')
if __name__ == '__main__':
work_1('file.txt',3)
work_2('file.txt',3)
'''
'''
# 多进程
import multiprocessing
import time
def work_1(f,n):
print('work_1 start')
for i in range(n):
with open(f,'a') as fs:
fs.write('i love python\n')
time.sleep(1)
print('work_1 end')
def work_2(f,n):
print('work_2 start')
for i in range(n):
with open(f,'a') as fs:
fs.write('come on baby \n')
time.sleep(1)
print('work_2 end')
if __name__ == '__main__':
p1=multiprocessing.Process(target=work_1,args=('file.txt',3))
p2=multiprocessing.Process(target=work_2,args=('file.txt',3))
p1.start()
p2.start()
'''
# 加锁
import multiprocessing
import time
def work_1(f,n,lock):
print('work_1 start')
lock.acquire()
for i in range(n):
with open(f,'a') as fs:
fs.write('i love python\n')
time.sleep(1)
print('work_1 end')
lock.release()
def work_2(f,n,lock):
print('work_2 start')
lock.acquire()
for i in range(n):
with open(f,'a') as fs:
fs.write('come on baby \n')
time.sleep(1)
print('work_2 end')
lock.release()
if __name__ == '__main__':
lock=multiprocessing.Lock()
p1=multiprocessing.Process(target=work_1,args=('file.txt',3,lock))
p2=multiprocessing.Process(target=work_2,args=('file.txt',3,lock))
p1.start()
p2.start()