递归锁、信号量、GIL锁、基于多线程的socket通信和进程池线程池

递归锁、信号量、GIL锁、基于多线程的socket通信和进程池线程池

递归锁

死锁现象:是指两个或两个以上的进程和线程因抢夺计算机资源而产生的一种互相等待的现象

from threading import Thread
from threading import Lock
import time
lock_A = Lock()
lock_B = Lock()
class MyThread(Thread):def run(self):self.f1()self.f2()def f1(self):lock_A.acquire()print(f"{self.name}拿到了A锁")lock_B.acquire()print(f"{self.name}拿到了B锁")lock_B.release()lock_A.release()def f2(self):lock_B.acquire()print(f"{self.name}拿到了B锁")time.sleep(0.1)lock_A.acquire()print(f"{self.name}拿到了A锁")lock_A.release()lock_B.release()
if __name__ == '__main__':for i in range(3):t = MyThread()t.start()
# 结果:
Thread-1拿到了A锁
Thread-1拿到了B锁
Thread-1拿到了B锁
Thread-2拿到了A锁

递归锁:

递归锁有一个计数的功能, 原数字为0,上一次锁,计数+1,释放一次锁,计数-1,

只要递归锁上面的数字不为零,其他线程就不能抢锁.

from threading import Thread
from threading import RLock
import time
lock_A = lock_B = RLock()
class MyThread(Thread):def run(self):self.f1()self.f2()def f1(self):lock_A.acquire()print(f"{self.name}拿到了A锁")lock_B.acquire()print(f"{self.name}拿到了B锁")lock_B.release()lock_A.release()def f2(self):lock_B.acquire()print(f"{self.name}拿到了B锁")time.sleep(0.1)lock_A.acquire()print(f"{self.name}拿到了A锁")lock_A.release()lock_B.release()
if __name__ == '__main__':for i in range(3):t = MyThread()t.start()

信号量

也是一种锁, 控制并发数量

from threading import Thread,Semaphore,current_thread
import time
import random
sem = Semaphore(5)
def task():sem.acquire()print(f"{current_thread().name}厕所ing")time.sleep(random.randint(1,3))print(f"{current_thread().name}厕所ed")sem.release()
if __name__ == '__main__':for i in range(20):t = Thread(target=task,)t.start()

GIL锁

GIL锁的定义:

全局解释锁,就是一把互斥锁,将并发变成串行,同一时刻只能有一个线程使用解释器资源,牺牲效率,保证解释器的数据安全。

py文件在内存中的执行过程:

  • 当执行py文件时,会在内存中开启一个进程
  • 进程中不光包括py文件还有python解释器,py文件中的线程会将代码交给解释器,
  • 解释器将python代码转化为C语言能识别的字节码,然后再交给解释器中的虚拟机将字节码转化为二进制码最后交给CPU执行

1729998-20190826210958038-1706557331.png

当线程1先拿到GIL锁时线程2、线程3就只能等待,当线程1在CPU执行遇到阻塞或执行一段时间后,线程1会被挂起,同时GIL锁会被释放,此时线程2或线程3就会拿到锁进入解释器,同样,当在CPU执行遇到阻塞或执行一段时间后被挂起,同时GIL锁会被释放,此时最后一个线程就会进入解释器。

从上面可以看出,当遇到单个进程中含有多个线程时,由于GIL锁的存在,Cpython并不能利用多核进行并行处理,但可以在单核实现并发。

但不同进程之间的多线程是可以利用多核的。

GIL锁的两个作用:

1、保证解释器里面的数据的安全;

2、强行加锁,减轻开发负担

问题:单进程的多线程不能利用多核

如何判断什么情况使用多线程并发与多进程并发

对计算来说,cpu越多越好,但是对于I/O来说,再多的cpu也没用

  当然对运行一个程序来说,随着cpu的增多执行效率肯定会有所提高(不管提高幅度多大,总会有所提高),这是因为一个程序基本上不会是纯计算或者纯I/O,所以应该相对的去看一个程序到底是计算密集型还是I/O密集型,如下:

#分析:
我们有四个任务需要处理,处理方式肯定是要达到并发的效果,解决方案可以是:
方案一:开启四个进程
方案二:一个进程下,开启四个线程#单核情况下,分析结果: 如果四个任务是计算密集型,没有多核来并行计算,方案一徒增了创建进程的开销,方案二胜如果四个任务是I/O密集型,方案一创建进程的开销大,且进程的切换速度远不如线程,方案二胜#多核情况下,分析结果:如果四个任务是计算密集型,多核意味着并行计算,在python中一个进程中同一时刻只有一个线程执行,可以利用多核,方案一胜如果四个任务是I/O密集型,再多的核也解决不了I/O问题,方案二胜#结论:现在的计算机基本上都是多核,python对于计算密集型的任务开多线程的效率并不能带来多大性能上的提升,甚至不如串行(没有大量切换),但是,对于IO密集型的任务效率还是有显著提升的。

总结:多核前提下,如果任务IO密集型,使用多线程并发;如果任务计算密集型,使用多进程并发。

验证Cpython的并发效率

  • 计算密集型: 单个进程的多线程并发 vs 多个进程的并发并行
from threading import Thread
from multiprocessing import Process
import time
import randomif __name__ == '__main__':# 多进程的并发,并行start_time = time.time()l1 = []for i in range(4):p = Process(target=task,)l1.append(p)p.start()for p in l1:p.join()print(f'执行效率:{time.time()- start_time}')  # 2.5342209339141846
from threading import Thread
from multiprocessing import Process
import time
import randomif __name__ == '__main__':
# 多线程的并发start_time = time.time()l1 = []for i in range(4):p = Thread(target=task,)l1.append(p)p.start()for p in l1:p.join()print(f'执行效率:{time.time()- start_time}')  # 5.262923240661621

​ 总结: 计算密集型: 多进程的并发并行效率高.

  • IO密集型: 单个进程的多线程并发 vs 多个进程的并发并行
from threading import Thread
from multiprocessing import Process
import time
import randomdef task():count = 0time.sleep(random.randint(1,3))count += 1if __name__ == '__main__':# 多进程的并发,并行start_time = time.time()l1 = []for i in range(50):p = Process(target=task,)l1.append(p)p.start()for p in l1:p.join()print(f'执行效率:{time.time()- start_time}')  #  7.145753383636475
from threading import Thread
from multiprocessing import Process
import time
import randomdef task():count = 0time.sleep(random.randint(1,3))count += 1if __name__ == '__main__':start_time = time.time()l1 = []for i in range(50):p = Thread(target=task,)l1.append(p)p.start()for p in l1:p.join()print(f'执行效率:{time.time()- start_time}')  # 3.0278055667877197

​ 总结:对于IO密集型: 单个进程的多线程的并发效率高.

基于多线程的socket通信

客户端:

import socketclient = socket.socket()client.connect(('127.0.0.1',8848))while 1:try:to_server_data = input('>>>').strip()client.send(to_server_data.encode('utf-8'))from_server_data = client.recv(1024)print(f'来自服务端的消息: {from_server_data.decode("utf-8")}')except Exception:break
client.close()

服务端:

import socket
from threading import Threaddef communicate(conn,addr):while 1:try:from_client_data = conn.recv(1024)print(f'来自客户端{addr[1]}的消息: {from_client_data.decode("utf-8")}')to_client_data = input('>>>').strip()conn.send(to_client_data.encode('utf-8'))except Exception:breakconn.close()def _accept():server = socket.socket()server.bind(('127.0.0.1', 8848))server.listen(5)while 1:conn, addr = server.accept()t = Thread(target=communicate,args=(conn,addr))t.start()if __name__ == '__main__':_accept()

进程池线程池

线程池: 一个容器,这个容器限制住你开启线程的数量,比如4个,第一次肯定只能并发的处理4个任务,只要有任务完成,线程马上就会接下一个任务.

from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor
import os
import time
import random# print(os.cpu_count()) 获取cpu数量
def task(n):print(f'{os.getpid()} 接客')time.sleep(random.randint(1,3))# 开启进程池  (并行(并行+并发))   
if __name__ == '__main__':p = ProcessPoolExecutor()  # 进程池,默认不写,开启数量为cpu数量for i in range(20):p.submit(task,i)# 开启线程池  (并发)t = ThreadPoolExecutor()  # 默认不写, cpu个数*5 线程数# t = ThreadPoolExecutor(100)  # 100个线程for i in range(20):t.submit(task,i)

转载于:https://www.cnblogs.com/lifangzheng/p/11415009.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/247067.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

10 种机器学习算法的要点(附 Python 和 R 代码)

前言 谷歌董事长施密特曾说过:虽然谷歌的无人驾驶汽车和机器人受到了许多媒体关注,但是这家公司真正的未来在于机器学习,一种让计算机更聪明、更个性化的技术。 也许我们生活在人类历史上最关键的时期:从使用大型计算机&#xff0…

8大策略让你对抗机器学习数据集里的不均衡数据

本文转自:http://www.36dsj.com/archives/35137 http://blog.csdn.net/heyongluoyao8/article/details/49408131 英文版本:http://machinelearningmastery.com/tactics-to-combat-imbalanced-classes-in-your-machine-learning-dataset/ 你是不是也经历…

线程queue、事件event及协程

线程queue、事件event及协程 线程queue 多线程抢占资源,让其保持串行的两种方式: ​ 1、互斥锁 ​ 2、队列 线程队列分为以下三种: 1、Queue(先进先出) import queueq queue.Queue(3) q.put(1) q.put(2) q.put(3) # q…

不平衡数据下的机器学习方法简介

本文转自:http://baogege.info/2015/11/16/learning-from-imbalanced-data/ 引言 不管是在学术界还是工业界,不平衡学习已经吸引了越来越多的关注,不平衡数据的场景也出现在互联网应用的方方面面,如搜索引擎的点击预测&#xff08…

Class Imbalance Problem

本文转自:http://www.chioka.in/class-imbalance-problem/#comment-202282 What is the Class Imbalance Problem? It is the problem in machine learning where the total number of a class of data (positive) is far less than the total number of another c…

程序代码编辑器和浏览器代码编辑器&代码可视化执行过程

tutorialspoint http://www.tutorialspoint.com/codingground.htm 1. Sublime Text :http://blog.l1n3.net/editor/sublime-text-introduce/ 下载 :http://www.sublimetext.com/3 2. Notepad https://notepad-plus-plus.org/zh/ 更多细节请查看 htt…

听技术播客:一边学Python编程一边学英语

本文转自:http://codingpy.com/article/recommended-python-podcasts/ 学技术的朋友一般都会关注不少技术博客(blog),但是关注技术播客(podcast)的人估计不会太多。这里一方面也是由于相关的播客数量&#…

mysql补充

mysql补充 mysql使用流程 开启服务端,mysqld或者net start mysqlcmd下键入mysql -u root -p,输入设置好的密码,连接mysql客户端show databases;展示所有的mysql仓库创建一个库:create database CRM;然后sho…

编程书单:十本Python编程语言的入门书籍

本文转自:http://codingpy.com/article/10-python-beginner-books/ 本文与大家分享一些Python编程语言的入门书籍,其中不乏经典。我在这里分享的,大部分是这些书的英文版,如果有中文版的我也加上了。有关书籍的介绍,大…

Sublime配置与各种插件

本文转自:http://www.cnblogs.com/yyhh/p/4232063.html Sublime Text 3 安装Package Control 点击View -> Show Console 在下方命令行内,输入以下命令。 import urllib.request,os;pfPackage Control.sublime-package;ippsublime.installed_packages_…

把Sublime Text 2打造成一个轻量级Python的IDE

本文转自:http://blog.l1n3.net/python/sublime-text-to-python-ide/ 因为这段时间迷上了Python,所以想吧Sublime Text 2弄成一个Python的简易IDE,Python自带的IDLE简直太难用!!!! 配置Python环…

数据库表操作、数据类型及完整性约束

数据库表操作、数据类型及完整性约束 库操作补充 数据库命名规则: 可以由字母、数字、下划线、@、#、$区分大小写唯一性不能使用关键字如 create select不能单独使用数字最长128位表操作补充 #语法: create table 表名…

第99:真正理解拉格朗日乘子法和 KKT 条件

转载于:https://www.cnblogs.com/invisible2/p/11441485.html

有了CodinGame,玩着游戏就能学编程

本文转自:http://www.codingpy.com/article/learning-to-code-becomes-a-game/ 今天编程派向大家推荐一个有趣的编程练习平台,而它与其他平台的差异,就在于它将编程练习变成了一个个游戏。这个平台的名字叫CodinGame,是一家法国创…

第98:svd原理

SVD分解:任何矩阵都可以分解成第一行的形式,3个相乘。UV都是正交矩阵,中间的是奇异值。 3个相乘的形式可以拆分。即奇异值*第一行*第一列。在相加。 奇异值有时很小,在这种情况下,丢掉,可以减少计算量&…

第97:一文读懂协方差与协方差矩阵

转载于:https://www.cnblogs.com/invisible2/p/11442777.html

设计模式之模板方法模式实战解析

本文微信公众号「AndroidTraveler」首发。 背景 最近在看《设计模式之禅》,为了能够更加深入的理解设计模式,达到学以致用。 这边记录一下自己的一些感受和看法,并结合具体代码实战来进行说明。 模板方法模式 但凡和设计模式挂上钩&#xff0…

第96:SVM简介与简单应用

详细推到见:https://blog.csdn.net/v_july_v/article/details/7624837 python实现方式: 转载于:https://www.cnblogs.com/invisible2/p/11448307.html

matlab如何把选中区域标亮

下面给出的是初始图像为彩色图像的情况。 %% Example on how to color select pixels in an image. % Kawahara (2013).% The original COLOR image. origImg imread(1.jpg); oldorigImg origImg; % Make sure the values are within 0-255. origImg uint8(origImg);% View…

Calendar是日历类

Calendar是日历类,在Date后出现,替换掉了许多Date的方法。该类将所有可能用到的时间信息封装为静态成员变量,方便获取。 Calendar为抽象类,由于语言敏感性,Calendar类在创建对象时并非直接创建,而是通过静态…