python之网络编程--锁、信号量、线程、队列
一、线程,可以发现顺序执行比开线程执行时间要短。原因是,一个进程中的多线程处理,由于存在GIL,并且GIL中只能存在一个线程,加上线程又存在切换的问题,所以时间耗得多。想要解决这个问题,是开几个进程,每个进程一个线程,就可以将cpu的多核利用起来,从而节省时间,不过进程对电脑消耗大,不建议开很多进程,因此可以用其他语言,Python不推荐
def add(): sum=0 for i in range(10000000): sum+=i print("sum",sum) def mul(): sum2=1 for i in range(1,100000): sum2*=i print("sum2",sum2) import threading,time start=time.time() t1=threading.Thread(target=add) t2=threading.Thread(target=mul) l=[] l.append(t1) l.append(t2) # for t in l: # t.start() # # # # for t in l: # t.join() add() mul() print("cost time %s"%(time.time()-start))
二、关于线程间执行顺序的例子,由于线程是并发的,执行速度很快,如果不sleep的话,可能很快就执行完了,答案是0,但是如果在中间休眠0.001s,会发现结果就不正常了,这是因为在上一个进程还没有计算完的时候,下一个进程就已经取得了数据,解决这个问题,可以用锁,只有锁内的代码执行完后才会执行其他内容。
import threading import time def sub(): global num # num-=1 # print ("ok") # lock.acquire() temp=num time.sleep(0.00001) num=temp-1 # lock.release() num=100 l=[] # lock=threading.Lock() for i in range(100): t=threading.Thread(target=sub) t.start() l.append(t) for t in l: t.join() print(num)
三、队列,put_nowait()相当于put(block=False),q = queue.Queue(3)里面的参数3代表,队列的大小为3个,其余的放不进去,必须等到队列里面有数被提出去了,才可以将数据放进来。
# import threading,time # # li=[1,2,3,4] # # # def pri(): # while li: # a=li[-1] # print(a) # time.sleep(1) # li.remove(a) # # try: # # li.remove(a) # # except Exception as e: # # print('----',a,e) # # t1=threading.Thread(target=pri,args=()) # t1.start() # t2=threading.Thread(target=pri,args=()) # t2.start() import queue # 线程 队列 q=queue.Queue(3) # FIFO模式 q.put(12) q.put("hello") q.put({"name":"yuan"}) q.put_nowait(56)# q.put(block=False) print(q.qsize()) print(q.empty()) print(q.full()) # q.put(34,False) while 1: data=q.get() print(data) print("----------") #先进后出 # import queue # q=queue.LifoQueue() # # q.put(12) # q.put("hello") # q.put({"name":"yuan"}) # # while 1: # data=q.get() # print(data) # print("----------") # q=queue.PriorityQueue() # # q.put([3,12]) # q.put([2,"hello"]) # q.put([4,{"name":"yuan"}]) # # while 1: # data=q.get() # print(data[1]) # print("----------")
四、线程中setDamon()运用,主线程退出,子线程也退出。
import threading # def foo(): # print("ok") # # # t1=threading.Thread(target=foo) # t1.start() # # print("ending...") # class MyThread(threading.Thread): # # def run(self): # print("ok") # # # t1=MyThread() # t1.start() # print('ending') import threading from time import ctime,sleep import time def ListenMusic(name): print ("Begin listening to %s. %s" %(name,ctime())) sleep(2)# sleep等同于IO操作 print("end listening %s"%ctime()) def RecordBlog(title): print ("Begin recording the %s! %s" %(title,ctime())) sleep(5) print('end recording %s'%ctime()) threads = [] t1 = threading.Thread(target=ListenMusic,args=('水手',)) t2 = threading.Thread(target=RecordBlog,args=('python线程',)) threads.append(t1) threads.append(t2) if __name__ == '__main__': #t1.setDaemon(True) t2.setDaemon(True) for t in threads: #t.setDaemon(True) #注意:一定在start之前设置 t.start() # t.join() #t1.join() #t1.setDaemon(True) #t2.join()########考虑这三种join位置下的结果? print ("all over %s" %ctime())
五、递归锁,用递归锁,解决死锁问题。
import threading import time class MyThread(threading.Thread): def actionA(self): r_lcok.acquire() #count=1 print(self.name,"gotA",time.ctime()) time.sleep(2) r_lcok.acquire() #count=2 print(self.name, "gotB", time.ctime()) time.sleep(1) r_lcok.release() #count=1 r_lcok.release() #count=0 def actionB(self): r_lcok.acquire() print(self.name, "gotB", time.ctime()) time.sleep(2) r_lcok.acquire() print(self.name, "gotA", time.ctime()) time.sleep(1) r_lcok.release() r_lcok.release() def run(self): self.actionA() self.actionB() if __name__ == '__main__': # A=threading.Lock() # B=threading.Lock() r_lcok=threading.RLock() L=[] for i in range(5): t=MyThread() t.start() L.append(t) for i in L: i.join() print("ending....")
六、生产者消费者模型
import time,random import queue,threading q = queue.Queue() def Producer(name): count = 0 while count <10: print("making........") time.sleep(5) 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(): # print("waiting.....") #q.join() data = q.get() print("eating....") time.sleep(4) q.task_done() #print(data) print('\033[32;1mConsumer %s has eat %s baozi...\033[0m' %(name, data)) # else: # print("-----no baozi anymore----") count +=1 p1 = threading.Thread(target=Producer, args=('A君',)) c1 = threading.Thread(target=Consumer, args=('B君',)) c2 = threading.Thread(target=Consumer, args=('C君',)) c3 = threading.Thread(target=Consumer, args=('D君',)) p1.start() c1.start() c2.start() c3.start()
七、同步对象,event的使用
import threading,time class Boss(threading.Thread): def run(self): print("BOSS:今晚大家都要加班到22:00。") print(event.isSet())# False event.set() time.sleep(5) print("BOSS:<22:00>可以下班了。") print(event.isSet()) event.set() class Worker(threading.Thread): def run(self): event.wait()# 一旦event被设定,等同于pass 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() print("ending.....")
八、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(3) thrs=[] for i in range(100): thrs.append(myThread()) for t in thrs: t.start()
九、进程调用
# from multiprocessing import Process # import time # # # def f(name): # time.sleep(1) # print('hello', name,time.ctime()) # # if __name__ == '__main__': # p_list=[] # for i in range(3): # # p = Process(target=f, args=('alvin',)) # 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): # time.sleep(1) # print ('hello', self.name,time.ctime()) # # # if __name__ == '__main__': # p_list=[] # # # for i in range(3): # p = MyProcess() # p.daemon=True # p.start() # p_list.append(p) # # # for p in p_list: # # p.join() # # print('end') from multiprocessing import Process import os import time def info(title): print("title:", title) print('parent process:', os.getppid()) print('process id:', os.getpid()) def f(name): info('function f') print('hello', name) if __name__ == '__main__': info('main process line') time.sleep(1) print("------------------") p = Process(target=info, args=('yuan',)) p.start() p.join()
笔记:
1.同步锁
2.死锁 递归锁
3.信号量和同步对象(了解)
4.队列------生产者消费者模型
5.进程
并发 & 并行
并发:是指系统具有处理多个任务(动作)的能力
并行:是指系统具有同时处理多个任务(动作)的能力
并行是并发的一个子集
几个线程是并发,因为有GIL,所以只能允许一个线程运行,是并发
几个进程是并行,可以解决线程不能同时运行的问题。可以几个CPU共同运行
同步 与 异步
同步:当进程执行到一个IO(等待外部数据)的时候,-----等:同步
异步: -----不等:异步
打电话是同步,发短信是异步
问题:多核没利用上?
GIL:Global_interpreter_lock全局解释锁
因为有GIL,所以同一时刻只有一个线程被CPU执行
任务:IO密集型 计算密集型
对于IO密集型的任务:python的多线程是有意义的
可以采用多进程+携程
对于计算密集型的任务:python的多线程就不推荐,python就不适用了,可以用其他语言。
信号量用来控制线程并发数的。