day 33 线程锁
Python的GIL锁
- Python内置的一个全局解释器锁,锁的作用就是保证同一时刻一个进程中只有一个线程可以被cpu调度。
为什么有这把GIL锁?
答:Python语言的创始人在开发这门语言时,目的快速把语言开发出来,如果加上GIL锁(C语言加锁),
切换时按照100条字节指令来进行线程间的切换。
一、锁: Lock
1、一次放一个
threading.Lock
线程安全,多线程操作时,内部会让所有线程排队处理。如:list/dict/ Queue
线性不安全 + 人 =》 排队处理
import threading v = []
def func(arg):
v.append(arg) # 线程安全
print(v)
for i in range(10):
t =threading.Thread(target=func,args=(i,))
t.start()
线性安全
import threading
import time v = []
lock = threading.Lock() def func(arg):
lock.acquire()
v.append(arg)
time.sleep(0.01)
m = v[-1]
print(arg,m)
lock.release() for i in range(10):
t =threading.Thread(target=func,args=(i,))
t.start()
锁Lock
import threading
import time v = []
lock = threading.RLock()
def func(arg):
lock.acquire()
lock.acquire() #RLock可以进行多次加锁 v.append(arg)
time.sleep(0.01)
m = v[-1]
print(arg,m) lock.release() #RLock多次释放锁
lock.release() for i in range(10):
t =threading.Thread(target=func,args=(i,))
t.start()
锁 Rlock
2、一次放指定N个
BoundedSemaphore
import time
import threading lock = threading.BoundedSemaphore(3) #3是一次指定释放的进程数量
def func(arg):
lock.acquire()
print(arg)
time.sleep(1)
lock.release() for i in range(20):
t =threading.Thread(target=func,args=(i,))
t.start()
BoundedSemaphore
3、一次释放N 个
Condition
import time
import threading
lock = threading.Condition()
# ############## 方式一 ##############
'''
def func(arg):
print('线程进来了')
lock.acquire()
lock.wait() # 加锁 print(arg)
time.sleep(1)
lock.release() for i in range(10):
t =threading.Thread(target=func,args=(i,))
t.start() while True:
inp = int(input('>>>')) lock.acquire()
lock.notify(inp) #输入几,lock.wait() 就是代表释放几个线程
lock.release()
# ############## 方式二 ############## def xxxx():
print('来执行函数了')
input(">>>")
# ct = threading.current_thread() # 获取当前线程
# ct.getName()
return True def func(arg):
print('线程进来了')
lock.wait_for(xxxx) #等待xxxx中的东西执行完成之后,此线程才会接着往下走
print(arg)
time.sleep(1) for i in range(10):
t =threading.Thread(target=func,args=(i,))
t.start()
4、一次放所有
Event
import time
import threading lock = threading.Event() def func(arg):
print('线程来了')
lock.wait() # 加锁:红灯
print(arg) for i in range(10):
t =threading.Thread(target=func,args=(i,))
t.start() input(">>>>")
lock.set() # 绿灯 lock.clear() # 再次变红灯 for i in range(10):
t =threading.Thread(target=func,args=(i,))
t.start() input(">>>>")
lock.set()
Event
总结
线程安全,列表和字典线程安全;
为什么要加锁?
- 非线程安全
- 控制一段代码
5、threading.local
作用:
内部自动为每个线程维护一个空间(字典),用于当前存取属于自己的值。保证线程之间的数据隔离。
{
线程ID: {...}
线程ID: {...}
线程ID: {...}
线程ID: {...}
}
import time
import threading v = threading.local() def func(arg):
# 内部会为当前线程创建一个空间用于存储:phone=自己的值
v.phone = arg
time.sleep(2)
print(v.phone,arg) # 去当前线程自己空间取值 for i in range(10):
t =threading.Thread(target=func,args=(i,))
t.start()
# by luffycity.com
import time
import threading DATA_DICT = {} def func(arg):
ident = threading.get_ident()
DATA_DICT[ident] = arg #就是每一个ID都会存放一个数据,查找的时候通过id查找数据
time.sleep(1)
print(DATA_DICT[ident],arg) for i in range(10):
t =threading.Thread(target=func,args=(i,))
t.start() #原理(深入了解)(可选)
import time
import threading
INFO = {}
class Local(object): def __getattr__(self, item):
ident = threading.get_ident()
return INFO[ident][item] def __setattr__(self, key, value):
ident = threading.get_ident()
if ident in INFO:
INFO[ident][key] = value
else:
INFO[ident] = {key:value} obj = Local() def func(arg):
obj.phone = arg # 调用对象的 __setattr__方法(“phone”,1)
time.sleep(2)
print(obj.phone,arg) for i in range(10):
t =threading.Thread(target=func,args=(i,))
t.start()
threadinglocal原理
6、线程池
创建多个线程池,用户需要几个线程去线程池里面去拿。(常用)
from concurrent.futures import ThreadPoolExecutor
import time def task(a1,a2):
time.sleep(2)
print(a1,a2) # 创建了一个线程池(最多5个线程)
pool = ThreadPoolExecutor(5) for i in range(40):
# 去线程池中申请一个线程,让线程执行task函数。
pool.submit(task,i,8)
7、生产者消费者模型
三部件:
生产者
队列,先进先出
扩展: 栈,后进先出
消费者 问:生产者消费者模型解决了什么问题?
不用一直等待的问题。
# by luffycity.com
import time
import queue
import threading
q = queue.Queue() # 线程安全 def producer(id):
"""
生产者
"""
while True:
time.sleep(2)
q.put('包子')
print('厨师%s 生产了一个包子' %id ) for i in range(1,4):
t = threading.Thread(target=producer,args=(i,))
t.start() def consumer(id):
"""
消费者
"""
while True:
time.sleep(1)
v1 = q.get()
print('顾客 %s 吃了一个包子' % id) for i in range(1,3):
t = threading.Thread(target=consumer,args=(i,))
t.start()
day 33 线程锁的更多相关文章
- day9---多线程,线程锁,队列
进程.线程 http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html 使用threading模块实现多线程编程[综述] Pyt ...
- Python 第八篇:异常处理、Socket语法、SocketServer实现多并发、进程和线程、线程锁、GIL、Event、信号量、进程间通讯
本节内容: 异常处理.Socket语法.SocketServer实现多并发.进程和线程.线程锁.GIL.Event.信号量.进程间通讯.生产者消费者模型.队列Queue.multiprocess实例 ...
- 托管C++线程锁实现 c++11线程池
托管C++线程锁实现 最近由于工作需要,开始写托管C++,由于C++11中的mutex,和future等类,托管C++不让调用(报错),所以自己实现了托管C++的线程锁. 该类可确保当一个线程位于 ...
- Java多线程面试题:线程锁+线程池+线程同步等
1.并发编程三要素? 1)原子性 原子性指的是一个或者多个操作,要么全部执行并且在执行的过程中不被其他操作打断,要么就全部都不执行. 2)可见性 可见性指多个线程操作一个共享变量时,其中一个线程对变量 ...
- python基础-12 多线程queue 线程交互event 线程锁 自定义线程池 进程 进程锁 进程池 进程交互数据资源共享
Python中的进程与线程 学习知识,我们不但要知其然,还是知其所以然.你做到了你就比别人NB. 我们先了解一下什么是进程和线程. 进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CP ...
- Python3学习之路~9.3 GIL、线程锁之Lock\Rlock\信号量、Event
一 Python GIL(Global Interpreter Lock) 全局解释器锁 如果一个主机是单核,此时同时启动10个线程,由于CPU执行了上下文的切换,让我们宏观上看上去它们是并行的,但实 ...
- NSLock线程锁的使用测试
测试1:NSLock线程锁是不是单例? 打印: 结论1:NSLock不是单例 测试2:同一个线程锁在不同的地方锁定,是否会有锁定两个? 打印为: 结论2:顺序打印,在不同的地方锁定也可以锁定. 测试3 ...
- python线程锁
import time,threading balance = 0 lock = threading.Lock() def change_it(n): global balance balance = ...
- linux下使用线程锁互斥访问资源
linux使用线程锁访问互斥资源: 1.线程锁的创建 pthread_mutex_t g_Mutex; 2.完整代码如下 #include <stdio.h> #include <s ...
随机推荐
- Hadoop环境部署
1.虚拟机克隆 在VM界面点击查看-自定义-库,然后在左边我的计算机下右键点击安装好的第一个系统,然后管理-克隆,选择克隆系统所在的文件路径即可. 2.三台主机名字修改 root用户下: (1)编辑n ...
- 如何在sprintf函数中输出百分号(%)等特殊符号
php中的sprinf可以格式化字符串的数据类型.今天遇到了想在其中输出%,可难倒我了. $query = sprintf("select * from books where %s li ...
- Mysql 索引类型+索引方法
MYSQL索引: PRIMARY(唯一且不能为空:一张表只能有一个主键索引). INDEX(普通索引). UNIQUE(唯一性索引). FULLTEXT(全文索引:用于搜索很长一篇文章的时候,效果最好 ...
- 从函数计算架构看 Serverless 的演进与思考
作者 | 杨皓然 阿里巴巴高级技术专家 导读:云计算之所以能够成为 DT 时代颠覆性力量,是因为其本质是打破传统架构模式.降低成本并简化体系结构,用全新的思维更好的满足了用户需求.而无服务器计算(S ...
- 学习笔记49_Redis
Redis和memcache区别: 1 . mm是通过客户端驱动实现集群化,Redis是通过服务器配置文件集群 2. redis是可以进行持久化的存储 3. redis提供高级的数据结构,队列,栈都提 ...
- 「刷题」卡特兰数&prufer序列
1.网格 转换模型,翻折容斥出解. 2.有趣的数列 抽象一下模型,把奇数项当作横坐标,偶数项当作纵坐标,就是从n*n矩阵左下角走到右上角并且每一步x<=y的方案数,发现是卡特兰数,关于gcd,可 ...
- 关于一道你们眼中的水题 Windy数 的乱写(数位dp)
啊一道水题有什么好说的 上课听不懂,下课泪两行. 有的人什么套路都会,我.. 只能可怜巴巴的抄代码,然后自己总结,顺(zhu)便(yao)颓博客 1.递推dp的思路做到一半死了,怎么也想不出来如何处理 ...
- 手机信号G、E、O、3G代表什么意思?
G指GPRS,是2.5G网络,属于GSM网络,也就是说这项技术位于第二代(2G)和第三代(3G)移动通讯技术之间,GPRS的传输速率可提升至56甚至114Kbps,已经将2017年确定为关闭GSM网络 ...
- NOIP模拟测试12
T1 斐波那契 一道找规律题,被我做成了贼难的题. 观察图片可知x=f[i-1]+j.(j为x的父亲)且j<=f[i-1],然后就二分找父亲没了. #include<bits/stdc++ ...
- netty源码解析(4.0)-28 ByteBuf内存池:PooledByteBufAllocator-把一切组装起来
PooledByteBufAllocator负责初始化PoolArena(PA)和PoolThreadCache(PTC).它提供了一系列的接口,用来创建使用堆内存或直接内存的PooledByteBu ...