操作系统
为什么要有操作系统?
操作系统:操作系统是一个用来协调,管理和控制计算机硬件和软件资源的系统程序。位于底层硬件与应用软件之间
工作方式:向下管理硬件 向上提供接口
切换
1.出现IO时切换
2.固定时间切换
进程
定义: 进程就是一个程序在一个数据集上的一次动态执行过程。
组成: 进程一般由程序、数据集、进程控制块三部分组成。
程序: 我们编写的程序用来描述进程要完成哪些功能以及如何完成;
数据集: 则是程序在执行过程中所需要使用的资源;
进程控制块: 用来记录进程的外部特征,描述进程的执行变化过程,系统可以利用它来控制和管理进程,它是系统感知进程存在的唯一标志。
线程
线程的出现是为了降低上下文切换的消耗,提高系统的并发性,并突破一个进程只能干一样事的缺陷,使到进程内并发成为可能。
线程也叫轻量级进程,它是一个基本的CPU执行单元,也是程序执行过程中的最小单元
组成:由线程ID、程序计数器、寄存器集合和堆栈共同组成。
线程的引入减小了程序并发执行时的开销,提高了操作系统的并发性能。线程没有自己的系统资源。
进程与线程的关系
进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。或者说进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。
线程则是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。
进程和线程的关系:
(1)一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
(2)资源分配给进程,同一进程的所有线程共享该进程的所有资源。
(3)CPU分给线程,即真正在CPU上运行的是线程。
并行和并发
并行处理(Parallel Processing)是计算机系统中能同时执行两个或更多个处理的一种计算方法。并行处理可同时工作于同一程序的不同方面。并行处理的主要目的是节省大型和复杂问题的解决时间。 指系统具有处理多个任务(动作)的能力
并发处理(concurrency Processing) 指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机(CPU)上运行,但任一个时刻点上只有一个程序在处理机(CPU)上运行 是指系统具有同时处理多个任务(动作)的能力
同步与异步
同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去;
异步是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率。举个例子,打电话时就是同步通信,发短息时就是异步通信。
线程 threading模块
Thread类直接创建
#直接通过多线程下的类实例出线程对象 #这个进程里面有三个线程,1个主线程,t1,t2两个子线程 #子线成和主线程是同步开启的,但主线程结束后,进程还没有关闭,子线程全部结束后进程才会关闭 import time import threading def countNum(n): # 定义某个线程要运行的函数 print("running on number:%s" %n) time.sleep(3) if __name__ == '__main__': t1 = threading.Thread(target=countNum,args=(23,)) #生成一个线程实例 t2 = threading.Thread(target=countNum,args=(34,)) t1.start() #启动线程 t2.start() print("ending!")
Thread类继承创建
import threading import time class MyThread(threading.Thread): def __init__(self,num): threading.Thread.__init__(self) self.num=num def run(self): #这个方法必须有,是start()方法里面触发的,没有run就会报错,和socket里面的handle()一样 print("running on number:%s" %self.num) time.sleep(3) print("running endind...") t1=MyThread(56) t2=MyThread(78) t1.start() t2.start() print("ending") #----------------- running on number:56 running on number:78 ending running endind... running endind...
Thread类方法
import threading import time def Music(name): print ("Begin {name}. {time}".format(name=name,time=time.ctime())) time.sleep(3) print("Ending {name}. {time}".format(name=name, time=time.ctime())) def Blog(name): print("Begin {name}. {time}".format(name=name, time=time.ctime())) time.sleep(5) print("Ending {name}. {time}".format(name=name, time=time.ctime())) t1 = threading.Thread(target=Music,args=('Alex',)) t2 = threading.Thread(target=Blog,args=('egon',)) t1.start() t2.start() t1.join() t2.join() print("end....") -----------------执行结果--------------- Begin Alex. Mon May 8 16:10:24 2017 Begin egon. Mon May 8 16:10:24 2017 Ending Alex. Mon May 8 16:10:27 2017 Ending egon. Mon May 8 16:10:29 2017 end.... -------------------------------------------------------------------------- import threading import time def Music(name): print ("Begin {name}. {time}".format(name=name,time=time.ctime())) time.sleep(3) print("Ending {name}. {time}".format(name=name, time=time.ctime())) def Blog(name): print("Begin {name}. {time}".format(name=name, time=time.ctime())) time.sleep(5) print("Ending {name}. {time}".format(name=name, time=time.ctime())) t1 = threading.Thread(target=Music,args=('Alex',)) t2 = threading.Thread(target=Blog,args=('egon',)) t1.start() t2.start() t1.join() print("end....") -----------------执行结果--------------- Begin Alex. Mon May 8 16:13:18 2017 Begin egon. Mon May 8 16:13:18 2017 Ending Alex. Mon May 8 16:13:21 2017 end.... Ending egon. Mon May 8 16:13:23 2017
# setDaemon(True): - 特点 将线程声明为守护线程,必须在start() 方法调用之前设置 1).如果子线程不设置为守护线程则如果子线程卡住,主程序也会被无限挂起。 2).但是有时候我们需要的是只要主线程完成了,不管子线程是否完成,都要和主线程一起退出,这时就可以用setDaemon方法 3).被设定守护的子线程理论上会和主线程一起运行结束,但是如果有多个子线程,而且不是全都守护线程的话, 主线程比子线程先结束的话主线程会等子线程执行完才会关闭进程,而且这个期间如果被守护的子线程能够执行完的话,他也会执行完 #事例一: (将两个子线程设置为守护线程,当主线程结束时,两个未执行完的子线程也结束) import threading import time def Music(name): print ("Begin {name}. {time}".format(name=name,time=time.ctime())) time.sleep(3) print("Ending {name}. {time}".format(name=name, time=time.ctime())) def Blog(name): print("Begin {name}. {time}".format(name=name, time=time.ctime())) time.sleep(5) print("Ending {name}. {time}".format(name=name, time=time.ctime())) threads = [] t1 = threading.Thread(target=Music,args=('Alex',)) t2 = threading.Thread(target=Blog,args=('egon',)) threads.append(t1) threads.append(t2) if __name__ == '__main__': for t in threads: t.setDaemon(True) #两个都设置为守护,不用管守护 t.start() print("end..") ---------------------执行结果------------------ Begin Alex. Thu Aug 17 18:08:37 2017 Begin egon. Thu Aug 17 18:08:37 2017 end.. #事例二:(t1设置为守护进程,t2执行完成后t1还未执行完,但这时t1也要随整个程序退出) import threading import time def Music(name): print("Begin {name}. {time}".format(name=name, time=time.ctime())) time.sleep(5) print("Ending {name}. {time}".format(name=name, time=time.ctime())) def Blog(name): print("Begin {name}. {time}".format(name=name, time=time.ctime())) time.sleep(3) print("Ending {name}. {time}".format(name=name, time=time.ctime())) threads = [] t1 = threading.Thread(target=Music, args=('Alex',)) t2 = threading.Thread(target=Blog, args=('egon',)) threads.append(t1) threads.append(t2) if __name__ == '__main__': t1.setDaemon(True) # t1设置为守护,不用管t1,当t2退出时,程序退出 for t in threads: t.start() print("end..") ---------------------执行结果------------------ Begin Alex. Thu Aug 17 18:39:59 2017 Begin egon. Thu Aug 17 18:39:59 2017 end.. Ending egon. Thu Aug 17 18:40:02 2017 #事例三: import threading import time def Music(name): print ("Begin {name}. {time}".format(name=name,time=time.ctime())) time.sleep(3) print("Ending {name}. {time}".format(name=name, time=time.ctime())) def Blog(name): print("Begin {name}. {time}".format(name=name, time=time.ctime())) time.sleep(5) print("Ending {name}. {time}".format(name=name, time=time.ctime())) threads = [] t1 = threading.Thread(target=Music,args=('Alex',)) t2 = threading.Thread(target=Blog,args=('egon',)) threads.append(t1) threads.append(t2) if __name__ == '__main__': t1.setDaemon(True) #t1设置为守护,不用管t1,当t2退出时,程序退出 for t in threads: t.start() print("end..") ---------------------执行结果------------------ Begin Alex. Mon May 8 16:57:45 2017 Begin egon. Mon May 8 16:57:45 2017 end.. Ending Alex. Mon May 8 16:57:48 2017 Ending egon. Mon May 8 16:57:50 2017
其它方法
Thread实例对象的方法 # isAlive(): 返回线程是否活动的。 # getName(): 返回线程名。 # setName(): 设置线程名。 threading模块提供的一些方法: # threading.currentThread(): 返回当前的线程变量。 # threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。 # threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
进程 multiprocessing
一.进程调用
import multiprocessing import time def f(name): time.sleep(1) print("hello",name,time.ctime()) # if __name__ == "main": if __name__ == '__main__': p_list = [] for i in range(3): p = multiprocessing.Process(target=f,args=("alex",)) p_list.append(p) p.start() for i in p_list: i.join() print("end")
from multiprocessing import Process import time class MyProcess(Process): def __init__(self ): super(MyProcess, self).__init__() # self.name = name def run(self): print ('hello', self.name,time.ctime()) time.sleep(1) if __name__ == '__main__': p_list=[] for i in range(3): p = MyProcess() p.start() p_list.append(p) for p in p_list: p.join()
二.process类
构造方法: Process([group [, target [, name [, args [, kwargs]]]]]) group: 线程组,目前还没有实现,库引用中提示必须是None; target: 要执行的方法; name: 进程名; args/kwargs: 要传入方法的参数。 实例方法: is_alive():返回进程是否在运行。 join([timeout]):阻塞当前上下文环境的进程程,直到调用此方法的进程终止或到达指定的timeout(可选参数)。 start():进程准备就绪,等待CPU调度 run():strat()调用run方法,如果实例进程时未制定传入target,这star执行t默认run()方法。 terminate():不管任务是否完成,立即停止工作进程 属性: daemon:和线程的setDeamon功能一样 name:进程名字。 pid:进程号。
from multiprocessing import Process import os import time def info(name): print("name:",name) print('parent process:', os.getppid()) print('process id:', os.getpid()) print("------------------") time.sleep(1) def foo(name): info(name) if __name__ == '__main__': info('main process line') p1 = Process(target=info, args=('alvin',)) p2 = Process(target=foo, args=('egon',)) p1.start() p2.start() p1.join() p2.join() print("ending")
三.进程间通信
进程彼此之间互相隔离,要实现进程间通信,即IPC,
multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的
同步锁(Lock)
加入同步锁,使用多线程,只是在锁内是串行的,其它部分还是多线程的
import time import threading R = threading.Lock() def addNum(): global num R.acquire() temp=num time.sleep(0.1) num =temp-1 R.release() num = 100 thread_list = [] for i in range(100): t = threading.Thread(target=addNum) t.start() thread_list.append(t) for t in thread_list: t.join() print(num)
线程死锁和递归锁
在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁,因为系统判断这部分资源都正在使用,所有这两个线程在无外力作用下将一直等待下去。下面是一个死锁的例子:
import threading,time class myThread(threading.Thread): def doA(self): lockA.acquire() print(self.name,"gotlockA",time.ctime()) time.sleep(3) lockB.acquire() print(self.name,"gotlockB",time.ctime()) lockB.release() lockA.release() def doB(self): lockB.acquire() print(self.name,"gotlockB",time.ctime()) time.sleep(2) lockA.acquire() print(self.name,"gotlockA",time.ctime()) lockA.release() lockB.release() def run(self): self.doA() self.doB() if __name__=="__main__": lockA=threading.Lock() lockB=threading.Lock() threads=[] for i in range(5): threads.append(myThread()) for t in threads: t.start() for t in threads: t.join() print("end...")
import threading,time class myThread(threading.Thread): def doA(self): Rlock.acquire() print(self.name,"gotlockA",time.ctime()) time.sleep(1) Rlock.acquire() print(self.name,"gotlockB",time.ctime()) Rlock.release() Rlock.release() def doB(self): Rlock.acquire() print(self.name,"gotlockB",time.ctime()) time.sleep(1) Rlock.acquire() print(self.name,"gotlockA",time.ctime()) Rlock.release() def run(self): self.doA() time.sleep(1) self.doB() if __name__=="__main__": Rlock=threading.RLock() threads=[] for i in range(5): threads.append(myThread()) for t in threads: t.start() for t in threads: t.join() print("end...")
同步条件(Event)
import threading,time class Boss(threading.Thread): def run(self): print("BOSS:今晚大家都要加班到22:00。") print(event.isSet()) event.set() time.sleep(5) print("BOSS:<22:00>可以下班了。") print(event.isSet()) event.set() class Worker(threading.Thread): def run(self): event.wait() print("Worker:哎……命苦啊!") time.sleep(1) event.clear() event.wait() print("Worker:OhYeah!") if __name__=="__main__": event=threading.Event() threads=[] for i in range(5): threads.append(Worker()) threads.append(Boss()) for t in threads: t.start() for t in threads: t.join()
信号量(Semaphore)
import threading,time class myThread(threading.Thread): def run(self): if semaphore.acquire(): print(self.name) time.sleep(3) semaphore.release() if __name__=="__main__": semaphore=threading.Semaphore(5) thrs=[] for i in range(20): thrs.append(myThread()) for t in thrs: t.start()
多线程利器---队列(queue)
创建一个“队列”对象 import Queue q = Queue.Queue(maxsize = 10) Queue.Queue类即是一个队列的同步实现。队列长度可为无限或者有限。可通过Queue的构造函数的可选参数maxsize来设定队列长度。如果maxsize小于1就表示队列长度无限。 将一个值放入队列中 q.put(10) 调用队列对象的put()方法在队尾插入一个项目。put()有两个参数,第一个item为必需的,为插入项目的值;第二个block为可选参数,默认为 1。如果队列当前为空且block为1,put()方法就使调用线程暂停,直到空出一个数据单元。如果block为0,put方法将引发Full异常。 将一个值从队列中取出 q.get() 调用队列对象的get()方法从队头删除并返回一个项目。可选参数为block,默认为True。如果队列为空且block为True, get()就使调用线程暂停,直至有项目可用。如果队列为空且block为False,队列将引发Empty异常。 Python Queue模块有三种队列及构造函数: 1、Python Queue模块的FIFO队列先进先出。 class queue.Queue(maxsize) 2、LIFO类似于堆,即先进后出。 class queue.LifoQueue(maxsize) 3、还有一种是优先级队列级别越低越先出来。 class queue.PriorityQueue(maxsize) 此包中的常用方法(q = Queue.Queue()): q.qsize() 返回队列的大小 q.empty() 如果队列为空,返回True,反之False q.full() 如果队列满了,返回True,反之False q.full 与 maxsize 大小对应 q.get([block[, timeout]]) 获取队列,timeout等待时间 q.get_nowait() 相当q.get(False) 非阻塞 q.put(item) 写入队列,timeout等待时间 q.put_nowait(item) 相当q.put(item, False) q.task_done() 在完成一项工作之后,q.task_done() 函数向任务已经完成的队列发送一个信号 q.join() 实际上意味着等到队列为空,再执行别的操作
import queue #先进后出 q=queue.LifoQueue() q.put(34) q.put(56) q.put(12) #优先级 # q=queue.PriorityQueue() # q.put([5,100]) # q.put([7,200]) # q.put([3,"hello"]) # q.put([4,{"name":"alex"}]) while 1: data=q.get() print(data)
生产者消费者模型:
为什么要使用生产者和消费者模式
在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。
什么是生产者消费者模式
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
这就像,在餐厅,厨师做好菜,不需要直接和客户交流,而是交给前台,而客户去饭菜也不需要不找厨师,直接去前台领取即可,这也是一个结耦的过程。
import time,random import queue,threading q = queue.Queue() def Producer(name): count = 0 while count <10: print("making........") time.sleep(random.randrange(3)) q.put(count) print('Producer %s has produced %s baozi..' %(name, count)) count +=1 #q.task_done() #q.join() print("ok......") def Consumer(name): count = 0 while count <10: time.sleep(random.randrange(4)) if not q.empty(): data = q.get() #q.task_done() #q.join() print(data) print('