0
点赞
收藏
分享

微信扫一扫

Python(七、GIL和深浅拷贝)

小沙坨 2021-09-27 阅读 60

GIL

"""
GIL(全局解释器锁)
GIL面试题如下
描述Python GIL的概念, 以及它对python多线程的影响?编写一个多线程抓取网页的程序,并阐明多线程抓取程序是否可比单线程性能有提升,并解释原因。

Guido的声明:http://www.artima.com/forums/flat.jsp?forum=106&thread=214235

he language doesn't require the GIL -- it's only the CPython virtual machine that has historically been unable to shed it.


Python语言和GIL没有半毛钱关系。仅仅是由于历史原因在Cpython虚拟机(解释器),难以移除GIL。
GIL:全局解释器锁。每个线程在执行的过程都需要先获取GIL,保证同一时刻只有一个线程可以执行代码。
线程释放GIL锁的情况: 在IO操作等可能会引起阻塞的system call之前,可以暂时释放GIL,但在执行完毕后,必须重新获取GIL Python 3.x使用计时器(执行时间达到阈值后,当前线程释放GIL)或Python 2.x,tickets计数达到100
Python使用多进程是可以利用多核的CPU资源的。
多线程爬取比单线程性能有提升,因为遇到IO阻塞会自动释放GIL锁


所以:因为gil的存在,计算密集型的代码不适合,因为不论怎样都会只有相当于一个核的cpu发挥作用
但是IO密集型,在一个线程等待的IO的时候,可以切换到其他线程进行继续的请求,所以爬虫这种多线程还是要比单线程效率高
"""

深浅拷贝

import copy

a = [1, 2]
b = a
# 浅拷贝
d = copy.copy(a)

# 深拷贝
c = copy.deepcopy(a)
# 复制引用的指向是相同的,所以b=a不能单纯的理解成浅拷贝,不相同
print(id(b), id(a), id(c), id(d))  # 140359854051912 140359854051912 140359854038984  140029529550792

a11 = [1, 2]
a12 = [3, 4]
a1 = [a11, a12]
b1 = copy.copy(a1)
print(id(b1), id(a1))  # 140044743117640 140044743117704
a12.append(5)
print(b1[1])  # [3, 4, 5]

b2 = copy.deepcopy(a1)
print(id(b1), id(a1))  # 139950679558984 139950679559048
a11.append(3)
print(b2[0])  # [1, 2]

"""
所以浅拷贝:针对的是只拷贝外部一层的引用,所以直接打印对应拷贝变量的id肯定是不同的
深拷贝:是直接复制数据到单独的空间
而复制引用:其实是索引赋值,内部外部都指向相同

浅拷贝:针对元组时候,因为元组是不可变的,所以浅拷贝相当于赋值引用,根本不会拷贝
copy.copy对于不可变类型,不会拷贝,仅仅是指向
"""

a = [11, 22]
b = [33, 44]
c = (a, b)
d = copy.copy(c)
e = copy.deepcopy(c)
print(id(c), id(d), id(e))  # 140187538002760 140187538002760  139729501239816

"""
如果元组(不可变类型)中数据也都是不可变类型,例如数字,则深浅拷贝针对元组其实都是不拷贝
但是如果元组中数据是可变类型,如上,则浅拷贝时候还是不拷贝,但是深拷贝的时候会从内到外全部拷贝一份(也就是说深拷贝时候不论多少层,只要有可变类型数据,则递归全部拷贝)
"""

# 其他拷贝方式
a = [1, 2]
b = [3, 4]
c = [a, b]
d = c[:]

# d=c[:]与d=copy.copy(c)一样属于浅拷贝


# 字典的copy方法可以拷贝一个字典(相当于浅拷贝)
d = dict(name="张安", age=29)
co = d.copy()
print(id(co), id(d))  # 140521022437488 140520998318872

举报

相关推荐

0 条评论