本站消息

  出租广告位,需要合作请联系站长

  今日名言-想象你自己对困难作出的反应,不是逃避或绕开它们,而是面对它们,同它们打交道,以一种进取的和明智的方式同它们奋斗 。——马克斯威尔·马尔兹

  今日名言-用谅解、宽恕的目光和心理看人、待人。人就会觉得葱笼的世界里,春意盎然,到处充满温暖。——蔡文甫


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

暂无数据

2021-7-23python学习日志

发布于2021-07-25 06:46     阅读(892)     评论(0)     点赞(10)     收藏(4)


今日内容概要

	1.死锁与递归锁
	2.线程队列Queue
	3.进程池和线程池
	4.协程
	5.greenlet模块
	6.gevent模块

今日内容详情

  • 死锁与递归锁

    	import time		
    	def eat1(lock1,lock2,name):
    	    lock1.acquire()
    	    print('%s谁抢到了筷子'%name)
    	    time.sleep(1)
    	    lock2.acquire()
    	    print('%s:抢到面条'%name)
    	    time.sleep(1)
    	    print('开始吃')
    	    time.sleep(1)
    	    lock2.release()
    	    print('面条放下了')
    	    lock1.release()
    	
    	def eat2(lock1,lock2,name):
    	    lock1.acquire()
    	    print('%s谁抢到了筷子' % name)
    	    time.sleep(1)
    	    lock2.acquire()
    	    print('%s:抢到面条' % name)
    	    time.sleep(1)
    	    print('开始吃')
    	    time.sleep(1)
    	    lock2.release()
    	    print('面条放下了')
    	    lock1.release()
    	死锁:
    		是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,
    		若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,
    		这些永远在互相等待的进程称为死锁进程,如下就是死锁
    		
    		from  threading import  Thread,Lock
    		if __name__ == '__main__':
    		    lock1=Lock()
    		    lock2=Lock()
    		    for i in ['wkj','www','WKJ']:
    		        t=Thread(target=eat1,args=(lock1,lock2,i))
    		        t.start()
    		    for i in ['QQQ','EEE','FFF']:
    		        t=Thread(target=eat2,args=(lock1,lock2,i))
    		        t.start()
    		        
    	解决方法:递归锁,在Python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock。        
    	递归锁:
    		from  threading import  Thread,RLock
    		if __name__ == '__main__':
    		    lock1=RLock()
    		    lock2=lock1
    		    for i in ['wkj','www','WKJ']:
    		        t=Thread(target=eat1,args=(lock1,lock2,i))
    		        t.start()
    		    for i in ['QQQ','EEE','FFF']:
    		        t=Thread(target=eat2,args=(lock1,lock2,i))
    		        t.start()
    		
    
  • 线程队列Queue

    	线程队列:
    		1.先进先出
    		2.后进先出
    		3.优先级队列
    		
    	from queue import Queue, LifoQueue, PriorityQueue
    	if __name__ == '__main__':
    	    # 1.先进先出
    	    q = Queue()
    	    q.put('ly is handsome1')
    	    q.put('ly is handsome2')
    	
    	    print(q.get())
    	
    	    # 2. 后进先出  堆, 栈。, 队列, 链表,
    	    q = LifoQueue()
    	    q.put('ly is handsome1')
    	    q.put('ly is handsome2')
    	    print(q.get())
    		# 3.优先级队列
    	    q = PriorityQueue()
    	    q.put((20, 'a'))
    	    q.put((10, 'b'))
    	    q.put((30, 'c'))
    	
    	    print(q.get())
    
  • 进程池和线程池

    	ThreadPoolExecutor:线程池,提供异步调用
    	ProcessPoolExecutor:进程池,提供异步调用
    	基本方法:
    		submit(fn, *args, **kwargs):异步提交任务
    		map(func, *iterables, timeout=None, chunksize=1):取代for循环submit的操作
    		shutdown(wait=True):相当于进程池的pool.close()+pool.join()操作
    		wait=True,等待池内所有任务执行完毕回收完资源后才继续
    		wait=False,立即返回,并不会等待池内的任务执行完毕
    			但不管wait参数为何值,整个程序都会等到所有任务执行完毕
    		submit和map必须在shutdown之前
    		result(timeout=None):取得结果
    		add_done_callback(fn):回调函数
    		done():判断某一个线程是否完成
    		cancle():取消某个任务
    		
    	from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor
    	def task(n):
    	    time.sleep(1)
    	    return n + n
    	def call_back(res):
    	    print(res.result())
    	
    	if __name__ == '__main__':
    	    urls = [1, 2, 3, 4]
    	    p1 = ProcessPoolExecutor(3)  # 里面有三个进程
    	    p2 = ThreadPoolExecutor(3)	 # 里面有三个线程
    	    for url in urls:
    	        p1.submit(task, url).add_done_callback(call_back)
    	    for url in urls:
    	        p2.submit(task, url).add_done_callback(call_back)
    	    print('ZJC')
    
  • 协程

    	协程:是一种用户态的轻量级线程,由用户程序自己控制调度得的
        强调:
            1.python的线程属于内核级别的,即由操作系统控制调度
                (如单线程遇到io或执行时间过长就会被迫交出cpu执行权限,切换其他线程运行)
            2.单线程内开启协程,一旦遇到io,就会从应用程序级别
                (而非操作系统)控制切换,以此来提升效率
                (!!!非io操作的切换与效率无关)
        优点:
            1.协程的切换开销更小,属于程序级别的切换,操作系统完全感知不到,因而更加轻量级
            2.单线程内就可以实现并发效果,最大限度地利用cpu
        缺点:
            1.协程的本质是单线程下,无法利用多核,可以是一个程序开启多个进程,
                每个进程内开启多个线程,每个线程内开启协程
            2.协程是单个线程,因而一旦协程出现阻塞,将会阻塞整个线程
        特点:
            1.必须在只有一个单线程里实现并发
            2.修改共享数据不需加锁
            3.用户程序里自己保存多个控制流的上下文栈
            4.一个协程遇到IO操作自动切换到其它协程
    
    
  • greenlet模块

    	安装:pip3 install greenlet
    	greenlet只是提供了一种比generator更加便捷的切换方式,当切到一个任务执行时如果遇到io,那就原地阻塞,仍然是没有解决遇到IO自动切换来提升效率的问题。
    	单线程里的这20个任务的代码通常会既有计算操作又有阻塞操作,我们完全可以在执行任务1时遇到阻塞,就利用阻塞的时间去执行任务2…如此,才能提高效率,这就用到了Gevent模块
    	
    	from greenlet import greenlet
    	def eat(name):
    	    print('%s:吃了一口'%name)
    	    g2.switch(name)
    	    print('%s:又吃了一口'%name)
    	    g2.switch()
    	def play(name):
    	    print('%s:玩了一下' % name)
    	    g1.switch()
    	    print('%s:又玩了一下' % name)
    	
    	g1=greenlet(eat)
    	g2=greenlet(play)
    	g1.switch('wkj')
    
  • gevent模块

    	安装:pip3 install gevent
    	gevent实现并发同步或异步编程,在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程。 Greenlet全部运行在主程序操作系统进程的内部,但它们被协作式地调度
    	import time
    	import gevent
    	def eat(name):
    	    print('%s:吃了一口'%name)
    	    gevent.sleep(2)
    	    print('%s:又吃了一口'%name)
    	def play(name):
    	    print('%s:玩了一下' % name)
    	    gevent.sleep(3)
    	    print('%s:又玩了一下' % name)
    	ctime=time.time()
    	g1=gevent.spawn(eat,'wkj')
    	g2=gevent.spawn(play,'wkj')
    	g1.join()
    	g2.join()
    	print(time.time()-ctime)
    
    	猴子补丁
    		什么是猴子补丁?
    		  1,这个词原来为Guerrilla Patch,杂牌军、游击队,说明这部分不是原装的,在英文里guerilla发音和gorllia(猩猩)相似,再后来就写了monkey(猴子)。
    		  2,还有一种解释是说由于这种方式将原来的代码弄乱了(messing with it),在英文里叫monkeying about(顽皮的),所以叫做Monkey Patch。
    	  名字听起来稀奇古怪的, 跟python的这个功能搭不上边。
    	  
    	  拥有在模块运行时替换的功能, 例如: 一个函数对象赋值给另外一个函数对象(把函数原本的执行的功能给替换了)
    	  
    	  这里有一个比较实用的例子,很多用到import json, 后来发现ujson性能更高,如果觉得把每个文件的import json改成import ujson as json成本较高, 或者说想测试一下ujson替换是否符合预期, 只需要在入口加上:
    	  import json
    		import ujson
    		def monkey_patch_json():
    		    json.__name__ = 'ujson'
    		    json.dumps = ujson.dumps
    		    json.loads = ujson.loads
    		monkey_patch_json()
    		aa=json.dumps({'name':'wkj','age':22})
    		print(aa)
    		
    

原文链接:https://blog.csdn.net/weixin_42213824/article/details/119034148



所属网站分类: 技术文章 > 博客

作者:小可爱不要爱

链接:http://www.pythonpdf.com/blog/article/478/07dee487ce94315bdaaf/

来源:编程知识网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

10 0
收藏该文
已收藏

评论内容:(最多支持255个字符)