一,回顾操做系统的概念python
操做系统位于底层硬件与应用软件之间的一层git
工做方式:向下管理软件,向上提供接口github
二,进程线程的概念redis
进程是一个资源单位,线程是一个最小的执行单位api
一个线程只能属于一个进程,而一个进程能够有多个线程,但至少有一个线程多线程
三,并行与并发并发
并行:
就是有多个进程能够同时运行的叫作并行
并发:
就是在一个处理器的状况下,切换执行,叫作并发
python没法实现并行处理,由于全局解释器锁gil致使同一时刻同一进程
只能有一个线程被运行。
GIL全局解释器锁
可是不影响Python开多进程
多线程代码示例
app
import threading import time ''' 程序在运行是有一个主线程,当程序开启多线程的时候,主线程依旧会执行, 主线程执行到最后时,并无结束,而是在等待子线程的结束后主线程结束 ''' def misc(): print("听歌") time.sleep(3) print("听歌结束") def xieboke(): print("写博客") time.sleep(5) print("写博客结束") #开启线程 t1=threading.Thread(target=misc)#t1,t2是一个线程对象 t2=threading.Thread(target=xieboke) t1.start() t2.start() print("主线程")
#开启多线程的另外一种方式
函数
import threading import time class MyThread(threading.Thread): ''' 用类的继承,继承线程的方法开启线程 ''' def __init__(self,num): ''' 继承父类的__init__方法 ''' threading.Thread.__init__(self) self.num=num def run(self): print("running on mythread:%s"%self.num) time.sleep(3) print("end%s"%self.num) t1=MyThread(10) t2=MyThread(20) t1.start() t2.start() print("主线程")
jion的使用
t.jion方法会阻塞主进程的运行,但不会影响其余线程的运行
setDaemon方法
-守护线程
当某个线程设置为守护线程的时候,它会随着主线程的结束而结束
t.setDaemon(True)
线程对象下的几个方法:
-isAlive()检测线程是否活动,返回值是布尔值
-getName():返回线程名
-setName():设置线程名称
threading模块提供的一些方法:
threading.currentTread():返回当前线程变量
threading.enumerate():返回一个包含正在运行的线程的list。
threading.activeCount():返回正在运行的线程数量
Python对于计算密集型运行比较慢,效率低;对于IO密集型效率有明显提升
Python多线程
互斥锁:
互斥锁的意义就是在保护锁内代码同一时间只有一个线程在使用
直到代码执行完成,解锁后其余线程才能执行所内代码。
使用格式:
-lock=threading.Lock()建立一把锁的对象
lock.acquire()#加锁
....须要保护的执行语句
lock.release()#解锁
死锁与递归锁
代码示例:
ui
import threading import time muteA=threading.Lock() muteB=threading.Lock() class MyThread(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): self.func1() self.func2() def func1(self): muteA.acquire() print("锁A执行内容",MyThread.getName(self)) muteB.acquire() print("锁B执行内容",MyThread.getName(self)) muteB.release() muteA.release() def func2(self): muteB.acquire() print("第二个函数的锁B",MyThread.getName(self)) muteA.acquire() print("第二个函数的锁A",MyThread.getName(self)) muteA.release() muteB.release() if __name__=="__main__": for i in range(10): my_thread=MyThread() my_thread.start()
造成死锁的缘由在于当线程1在第二个函数中拿到锁B向下执行须要锁A的时候,线程2在函数1中 已经拿到的锁A,在等待线程1释放B。两个线程都没有释放另外一个线程须要的锁,因此就造成了死锁。 递归锁的应用 递归锁未避免死锁的产生,在锁内实行一个引用计数,当有一把使用是计速器加一,释放后,去除计数 到代码在执行锁内代码时,若是有其余线程抢锁,计数若是为零,线程能够拿到锁,大于零,拒绝线程拿锁 这样就能避免锁的重复,也就不会产生死锁 代码示例: import threading import time Rlock=threading.Rlock() class MyThread(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): self.func1() self.func2() def func1(self): Rlock.acquire() print("锁A执行内容",MyThread.getName(self)) Rlock.acquire() print("锁B执行内容",MyThread.getName(self)) Rlock.release() Rlock.release() def func2(self): Rlock.acquire() print("第二个函数的锁B",MyThread.getName(self)) Rlock.acquire() print("第二个函数的锁A",MyThread.getName(self)) Rlock.release() Rlock.release() if __name__=="__main__": for i in range(10): my_thread=MyThread() my_thread.start() event方法使用: event方法可让两个线程之间通讯,当一个线程须要另外一个线程准备数据的时候, event.wait(),阻塞程序的运行,直到另外一个线程将数据准备完成后,使用event.set() 返回一个true值,event.wait()接受到该值以后,线程开始运行。wait方法后能够接一个超时 时间参数,规定在必定时间内阻塞,超时后运行。 import threading import time import logging logging.basicConfig(level=logging.DEBUG, format='(%(threadName)-10s) %(message)s',) def worker(event): logging.debug('Waiting for redis ready...') while not event.isSet(): logging.debug("wait.......") event.wait(3) # if flag=False阻塞,等待flag=true继续执行 logging.debug('redis ready, and connect to redis server and do some work [%s]', time.ctime()) time.sleep(1) def main(): readis_ready = threading.Event() # flag=False建立一个event对象 t1 = threading.Thread(target=worker, args=(readis_ready,), name='t1') t1.start() t2 = threading.Thread(target=worker, args=(readis_ready,), name='t2') t2.start() logging.debug('first of all, check redis server, make sure it is OK, and then trigger the redis ready event') time.sleep(6) # simulate the check progress readis_ready.set() # flag=Ture if __name__=="__main__": main() 进程multprocessing模块 multprocessing模块与threading模块使用同一套api,使用方法调用方法与threading模块同样 代码示例: from multiprocessing import Process import time def f(name): print("hello",name,time.ctime()) time.sleep(1) if __name__=="__main__": p_list=[] for i in range(3): p=Process(target=f,args=("alvin:%s"%i,)) p_list.append(p) p.start() 协程的应用: 协程是单线程的,不能切换。由于协程对IO操做的判断由本身控制 import time # 能够实现并发 def consumer(): r = '' while True: n = yield r if not n: return print('[CONSUMER] ←← Consuming %s...' % n) time.sleep(1) r = '200 OK' def produce(c): next(c) n = 0 while n < 5: n = n + 1 print('[PRODUCER] →→ Producing %s...' % n) cr = c.send(n) print('[PRODUCER] Consumer return: %s' % cr) c.close() if __name__=='__main__': c = consumer() produce(c) gevent模块的使用: from gevent import monkey monkey.patch_all() import gevent from urllib import request import time def f(url): print('GET: %s' % url) resp = request.urlopen(url) data = resp.read() print('%d bytes received from %s.' % (len(data), url)) start=time.time() gevent.joinall([ gevent.spawn(f, 'https://itk.org/'), gevent.spawn(f, 'https://www.github.com/'), gevent.spawn(f, 'https://zhihu.com/'), ]) #f('https://itk.org/') #f('https://www.github.com/') #f('https://zhihu.com/') print(time.time()-start)