智能网站价格,淄博网站建设铭盛信息,做电商网站的框架结构图,常用的软件开发平台一、 互斥锁(Lock)与递归锁(RLock)机制1.1 由互斥锁(Lock)产生的死锁现象#xff1a;#互斥锁(死锁现象)#xff1a;#死锁现象#xff1a;from threading importLocklockLock()lock.acquire()print(123)lock.acquire()#等待获取锁(死锁状态)print(456)lock.release()#等待释放…一、 互斥锁(Lock)与递归锁(RLock)机制1.1 由互斥锁(Lock)产生的死锁现象#互斥锁(死锁现象)#死锁现象from threading importLocklockLock()lock.acquire()print(123)lock.acquire()#等待获取锁(死锁状态)print(456)lock.release()#等待释放锁lock.release()print(程序结束)#科学家吃面产生的死锁现象from threading importLock, Threadimporttimenoodle_lock Lock() #面条锁fork_lock Lock() #叉子锁defeat1(name):noodle_lock.acquire()time.sleep(0.5)print(%s拿到面了 %name)fork_lock.acquire()print(%s拿到叉子了 %name)print(%s吃面 %name)fork_lock.release()print(%s放下叉子了 %name)noodle_lock.release()print(%s放下面了 %name)defeat2(name):fork_lock.acquire()print(%s拿到叉子了 %name)noodle_lock.acquire()print(%s拿到面了 %name)print(%s吃面 %name)noodle_lock.release()print(%s放下面了 %name)fork_lock.release()print(%s放下叉子了 %name)#三个线程(科学家)需同时获取叉子和面条才能吃到面条Thread(targeteat1, args(Annie,)).start()Thread(targeteat2, args(Lisa,)).start()Thread(targeteat1, args(Jane,)).start()View Code1.2 解决由互斥锁产生的死锁可重入锁(递归锁RLock)解决方法#递归锁(可重入锁)#方式一#RLock解决死锁问题(建议少用递归锁一般程序的递归锁的出现都是程序设计不合理导致)from threading importRLock, Threadimporttimefork_lock noodle_lock RLock()defeat1(name):noodle_lock.acquire()#获取递归锁(进入第一层)print(%s拿到面了 %name)time.sleep(0.5)fork_lock.acquire()#获取递归锁(进入第二层)print(%s拿到叉子了 %name)print(%s吃面 %name)fork_lock.release()#释放递归锁(出第二层)print(%s放下叉子了 %name)noodle_lock.release()#释放递归锁(出第一层)print(%s放下面了 %name)defeat2(name):fork_lock.acquire()print(%s拿到叉子了 %name)noodle_lock.acquire()print(%s拿到面了 %name)print(%s吃面 %name)noodle_lock.release()print(%s放下面了 %name)fork_lock.release()print(%s放下叉子了 %name)Thread(targeteat1, args(Annie,)).start() #线程一Thread(targeteat2, args(Lisa,)).start() #线程二Thread(targeteat1, args(Jane,)).start() #线程三#方式二#直接使用互斥锁结果科学家吃面问题from threading importLock, ThreadlockLock()defeat1(name):lock.acquire()#获取锁print(%s拿到面了 %name)print(%s拿到叉子了 %name)print(%s吃面 %name)print(%s放下叉子了 %name)print(%s放下面了 %name)lock.release()#释放锁defeat2(name):lock.acquire()print(%s拿到叉子了 %name)print(%s拿到面了 %name)print(%s吃面 %name)print(%s放下面了 %name)print(%s放下叉子了 %name)lock.release()Thread(targeteat1, args(Annie,)).start() #线程一Thread(targeteat2, args(Lisa,)).start() #线程二Thread(targeteat1, args(Jane,)).start() #线程三View Code1.3 总结gil锁机制保证线程同一时刻只能一个线程访问CPU,不可能有两个线程同时在CPU上执行指令lock锁机制保证某一段代码 在没有执行完毕之后,不可能有另一个线程也执行这一段代码二、 线程锁实现为什么要使用线程锁1. 同一时刻同一段代码,只能有一个进程来执行这段代码2. 锁的应用场景,当多个进程需要操作同一个文件/数据库的时候 ,3. 会产生数据不安全,我们应该使用锁来避免多个进程同时修改一个文件示例#示例importjsonimporttimefrom multiprocessing importProcess, Lock#查询余票defsearch_ticket(name):with open(ticket, encodingutf-8) as f:dicjson.load(f)print(%s查询余票为%s % (name, dic[count]))#购买车票defbuy_ticket(name):with open(ticket, encodingutf-8) as f:dicjson.load(f)time.sleep(2)if dic[count] 1:print(%s买到票了 %name)dic[count] - 1time.sleep(2)with open(ticket, modew, encodingutf-8) as f:json.dump(dic, f)else:print(余票为0,%s没买到票 %name)#使用线程锁方式一defuse1(name, lock):search_ticket(name)print(%s在等待 %name)lock.acquire()#获取锁print(%s开始执行了 %name)buy_ticket(name)lock.release()#释放锁#使用线程锁方式二defuse2(name, lock):# with lock:# 代码块# 上下文管理在__enter__方法中获取锁(acquire)在__exit__方法中释放锁(release)search_ticket(name)print(%s在等待 %name)with lock:#获取锁 释放锁print(%s开始执行了 %name)buy_ticket(name)if __name__ __main__:lockLock()l [alex, wusir, baoyuan, taibai]for name inl:Process(targetuse1, args(name, lock)).start() #方式一Process(targetuse2, args(name, lock)).start() #方式二View Code三、 队列(QueueLifoQueuePriorityQueue)的使用3.1 先进先出队列(Queue):#先进先出队列#Queue就是一个线程队列的类,自带lock锁,实现了线程安全的数据类型from queue importQueueqQueue()q.put({1, 2, 3})q.put_nowait(abc)print(q.get_nowait()) #获取一个值如果没有抛出异常print(q.get())q.empty()#判断是否为空q.full() #判断是否为满q.qsize() #查看队列的大小View Code3.2 先进后出队列(栈LifoQueue):#先进后出的队列(last in first out):#线程安全的队列 栈和后进先出的场景都可以用from queue importLifoQueuelfqLifoQueue()lfq.put(1)lfq.put(abc)lfq.put({1, 2})print(lfq.get()) #{2, 1}print(lfq.get()) #abcprint(lfq.get()) #1View Code3.3 优先级队列(PriorityQueue):#优先级队列:from queue importPriorityQueuepqPriorityQueue()pq.put((10, aaa))pq.put((2, bbb))pq.put((20, ccc))print(pq.get()) #最想获取到优先级最高的2,以元组形式返回 (2, bbb)print(pq.get()) #(10, aaa)print(pq.get()) #(20, ccc)View Code四、线程队列(生产者与消费者模型)#生产者与消费者示例importtimeimportrandomfrom queue importQueuefrom threading importThread#生产者defproducer(q):for i in range(10):time.sleep(random.random())food Spam %s %iprint(%s生产了%s % (Jane, food))q.put(food)#消费者defconsumer(q, name):whileTrue:food q.get() #food 食物/Noneif not food: break #当消费者消费完成后最后拿到None时退出消费者程序time.sleep(random.uniform(1, 2))print(%s 吃了 %s %(name, food))if __name__ __main__:qQueue()p1 Thread(targetproducer, args(q,)) #生产者p1.start()c1 Thread(targetconsumer, args(q, Lisa)) #消费者c1.start()c2 Thread(targetconsumer, args(q, Annie)) #消费者c2.start()p1.join()q.put(None)#生产者完成生产后队列最后加入None表示已经生产完成q.put(None) #每个消费者需要None退出程序View Code五、守护线程5.1 守护线程的定义1. 主线程会等待子线程的结束而结束2. 守护线程会守护主线程和所有的子线程3. 守护线程会随着主线程的结束而结束主线程结束进程资源回收守护线程被销毁示例#守护线程示例importtimefrom threading importThread#守护线程defdaemon_func():whileTrue:time.sleep(0.5)print(守护线程)#其他子线程defson_func():print(start son)time.sleep(5)print(end son)t Thread(targetdaemon_func) #开启守护线程t.daemon Truet.start()Thread(targetson_func).start() #开启son_func子线程time.sleep(3)print(主线程结束) #主线程代码结束后等待子线程son_func结束View Code总结守护进程 :只会守护到主进程的代码结束守护线程 :会守护所有其他非守护线程的结束六、线程池线程池模块与进程池共用同一个模块concureent.futures示例#线程池from urllib.request importurlopenfrom concurrent.futures import ThreadPoolExecutor #导入线程池类#获取网页defget_html(name, addr):returlopen(addr)return {name: name, content: ret.read()}#保存数据defcache_page(ret_obj):dicret_obj.result()with open(dic[name] .html, wb) as f:f.write(dic[content])url_dic{协程: http://www.cnblogs.com/Eva-J/articles/8324673.html,线程: http://www.cnblogs.com/Eva-J/articles/8306047.html,目录: https://www.cnblogs.com/Eva-J/p/7277026.html,百度: http://www.baidu.com,sogou: http://www.sogou.com}#创建20个线程#方式一t ThreadPoolExecutor(20) #实例化线程池对象for url inurl_dic:task t.submit(get_html, url, url_dic[url]) #提交线程任务task.add_done_callback(cache_page) #函数回调数据保存#方式二with ThreadPoolExecutor(20) as t: #上下文管理方式实现实例化的线程池for url inurl_dic:taskt.submit(get_html, url, url_dic[url])task.add_done_callback(cache_page)View Code