首页 > 编程语言 > 详细

GIL与线程进程小知识点

时间:2019-05-08 16:15:01      阅读:130      评论:0      收藏:0      [点我收藏+]

一 、GIL全局解释器

GIL是一个互斥锁:保证数据的安全(以牺牲效率来换取数据的安全)
阻止同一个进程内多个线程同时执行(不能并行但是能够实现并发)
并发:看起来像同时进行的
GIL全局解释器存在的原因是因为Cpython解释器的内存管理不是线程安全的

垃圾回收机制
1.引用计数
2.标记清除
3.分代回收

同一个进程下的多个线程不能实现并行但是能够实现并发,多个进程下的线程能够实现并行

问题:python多线程是不是就没有用了呢?
四个任务:计算密集的任务 每个任务耗时10s
单核情况下:
多线程好一点,消耗的资源少一点
多核情况下:
开四个进程:10s多一点
开四个线程:40s多一点

四个任务:IO密集的任务 每个任务io 10s
单核情况下:
多线程好一点
多核情况下:
多线程好一点
多线程和多进程都有自己的优点,要根据项目需求合理选择

 

# 计算密集型
from multiprocessing import Process
from threading import Thread
import os,time
def work():
res=0
for i in range(100000000):
res*=i


if __name__ == ‘__main__‘:
l=[]
print(os.cpu_count())   # 本机为4核
start=time.time()
for i in range(4):
# p=Process(target=work)   #耗时13.018355369567871
p=Thread(target=work)   #耗时25.032227754592896
l.append(p)
p.start()
for p in l:
p.join()
stop=time.time()
print(‘run time is %s‘ %(stop-start))

 

# IO密集型
from multiprocessing import Process
from threading import Thread
import threading
import os,time


def work():
time.sleep(2)


if __name__ == ‘__main__‘:
l=[]
print(os.cpu_count())   #本机为4核
start=time.time()
for i in range(600):
p=Process(target=work)   #耗时4.699530839920044
# p=Thread(target=work)   #耗时2.054128885269165
l.append(p)
p.start()
for p in l:
p.join()
stop=time.time()
print(‘run time is %s‘ %(stop-start))

 

二 、 GIL与普通锁对比

 

from threading import Thread,Lock
import time

mutex = Lock()

n = 100

def task():
global n
mutex.acquire()
tmp = n
time.sleep(0.1)
n = tmp - 1
mutex.release()

t_list = []
for i in range(100):
t = Thread(target=task)
t.start()
t_list.append(t)

for t in t_list:
t.join()

print(n)

 

-->>  0

对于不同的数据,要想保证安全,需要加不同的锁处理
GIL并不能保证数据的安全,它是对Cpython解释器加锁,针对的是线程
保证的是同一个进程下多个线程之间的安全

 

三 、死锁与递归锁(了解)

 

from threading import Thread,Lock,RLock
import time

"""
自定义锁一次acquire必须对应一次release,不能连续acquire
递归锁可以连续的acquire,每acquire一次计数加一:针对的是第一个抢到我的人
"""

#
# mutexA = Lock()
# mutexB = Lock()
mutexA = mutexB = RLock() # 抢锁之后会有一个计数 抢一次计数加一 针对的是第一个抢到我的人

class MyThread(Thread):
def run(self):
self.func1()
self.func2()

def func1(self):
mutexA.acquire()
print(‘%s 抢到A锁了‘%self.name)
mutexB.acquire()
print(‘%s 抢到B锁了‘ % self.name)
mutexB.release()
print(‘%s 释放了B锁‘%self.name)
mutexA.release()
print(‘%s 释放了A锁‘%self.name)

def func2(self):
mutexB.acquire()
print(‘%s 抢到了B锁‘%self.name)
time.sleep(1)
mutexA.acquire()
print(‘%s 抢到A锁了‘ % self.name)
mutexA.release()
print(‘%s 释放了A锁‘ % self.name)
mutexB.release()
print(‘%s 释放了B锁‘ % self.name)


for i in range(100):
t = MyThread()
t.start()

 

四 、 信号量(了解)

 

from threading import Thread,Semaphore
import time
import random
sm = Semaphore(5) # 五个厕所五把锁
# 跟你普通的互斥锁区别在于,普通的互斥锁是独立卫生间,所有人抢一把锁
# 信号量 公共卫生间 有多个坑,所有人抢多把锁

 

def task(name):
sm.acquire()
print(‘%s正在蹲坑‘%name)
# 模拟蹲坑耗时
time.sleep(random.randint(1,5))
sm.release()


if __name__ == ‘__main__‘:
for i in range(20):
t = Thread(target=task,args=(‘伞兵%s号‘%i,))
t.start()

 

五 、 event事件(了解)

 

from threading import Event,Thread
import time
import random


event = Event()


def light():
print(‘红灯亮着!‘)
time.sleep(3)
event.set()    # 解除阻塞,给我的event发了一个信号
print(‘绿灯亮了!‘)


def car(i):
print(‘%s 正在等红灯了‘%i)
event.wait()    # 阻塞
print(‘%s 加油门飙车了‘%i)

t1 = Thread(target=light)
t1.start()


for i in range(10):
t = Thread(target=car,args=(i,))
t.start()

 

六 、线程Queue(了解)

 

import queue

# 1.普通q
# 2.先进后出q
# 3.优先级q


# q=queue.Queue(3)
# q.put(1)
# q.put(2)
# q.put(3)
# print(q.get())
# print(q.get())
# print(q.get())

# q = queue.LifoQueue(5)
# q.put(1)
# q.put(2)
# q.put(3)
# q.put(4)
# print(q.get())

 

# 优先级q
# q = queue.PriorityQueue()
# q.put((10,‘a‘))
# q.put((-1,‘b‘))
# q.put((100,‘c‘))
# print(q.get())
# print(q.get())
# print(q.get())

 

GIL与线程进程小知识点

原文:https://www.cnblogs.com/SlookUp/p/10832440.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!