一丶锁

  线程安全:

    线程安全能够保证多个线程同时执行时程序依旧运行正确, 而且要保证对于共享的数据,可以由多个线程存取,但是同一时刻只能有一个线程进行存取.

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()

线程安全

  1.GIL锁

    GIL锁中文名称为"全局解释器锁",主要体现在多线程中,每个线程在执行的过程中都需要先获取GIL,保证同一时刻只有一个线程可以执行代码.而Python语言和GIL没有半毛钱关系,仅仅是由于历史原因在Cpython虚拟机(解释器),难以移除GIL

    补充:

      (线程释放GIL锁的情况)在IO操作等可能会引起阻塞的system call之前,可以暂时释放GIL,但在执行完毕后,必须重新获取GIL. Python 3.x使用计时器(执行时间达到阈值后,当前线程释放GIL)或Python 2.x,tickets计数达到100,多线程爬取比单线程性能有所提升,因为遇到IO阻塞会自动释放GIL锁.

  2.Lock锁(一次放一个)

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() # 不加锁: #加锁后
# 2 9 0 0
# 3 9 1 1
# 0 9 2 2
# 1 9 3 3
# 7 9 4 4
# 5 9 5 5

Lock

  3.RLock锁(一次放一个)

import threading
import time v = []
lock = threading.RLock()
def func(arg):
lock.acquire()
lock.acquire() v.append(arg)
time.sleep(0.01)
m = v[-1]
print(arg,m) lock.release()
lock.release() for i in range(10):
t =threading.Thread(target=func,args=(i,))
t.start() # 结果:
# 0 0
# 1 1
# 2 2
# 3 3
# 4 4
# 5 5

RLock

  Lock和RLock 的区别:

    Lock:Lock(指令锁)是可用的最低级别的同步指令.Lock处于锁定状态时,不被特定的线程拥有.Lock包含两种状态--锁定和非锁定,以及两个基本方法.可以认为Lock有一个锁定值池,当线程请求锁定时,将线程至于池中,知道获得锁定后出池.池中的线程处于状态图中的同步阻塞状态.

  RLock(可重入锁)是一个可以被同一个线程请求多次的同步指令.RLock使用了"拥有的线程"和"递归等级"的概念,处于锁定状态时,RLock被某个线程拥有.拥有RLock的线程可以再次调用acquire(),释放锁时需要调用release()相同次数.可以认为RLock包含一个锁定池和一个初始值为0的计数器,每次成功调用acquire()/release(),计数器将+1/-1,为0时锁处于未锁定状态

  简言之: Lock属于全局,Rlock属于线程

  4.BoundedSemaphore(一次放指定个数)

import time
import threading lock = threading.BoundedSemaphore(4) #每次允许通过的个数
def func(arg):
lock.acquire() #加锁
print(arg)
time.sleep(2)
lock.release() #解锁 for i in range(10):
t =threading.Thread(target=func,args=(i,))
t.start()

BoundedSemaphore

  5.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.release() #结果:
# 线程进来了
# ....
# 线程进来了
# >>>3
# >>>0
#
#
#
# >>>3
#
#
# >>>5
#
#
#
#
# >>>9 # ############## 方式二(输入一次放一个)##############
# def xxxx():
print('来执行函数了')
input(">>>")
# ct = threading.current_thread() # 获取当前线程
# ct.getName()
return True def func(arg):
print('线程进来了')
lock.wait_for(xxxx)
print(arg)
time.sleep(1) for i in range(10):
t =threading.Thread(target=func,args=(i,))
t.start() #结果
# >> > 线程进来了
# 来执行函数了
# >> > 线程进来了
# 来执行函数了
# >> > 1
#
#
#
#
#
#

Condition

  6.Event(一次放所有)

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

二丶threading.local

  作用:内部自动为每一个线程维护一个空间(字典),用于当前存取属于自己的值.保证线程之间的数据隔离

  {

  线程ID: {.....}

  线程ID: {.....}

  线程ID: {.....}

}

import time
import threading DATA_DICT = {} def func(arg):
ident = threading.get_ident() #获取线程ID
DATA_DICT[ident] = arg #{1756: 0, 2636: 1, 8892: 2, 8448: 3, 2344: 4, 7196: 5, 8572: 6, 2268: 7, 2480: 8, 7644: 9}
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()
print(INFO)#{7688: {'phone': 0}, 8972: {'phone': 1}, 5280: {'phone': 2}, 4724: {'phone': 3},
# 8384: {'phone': 4}, 8680: {'phone': 5}, 8220: {'phone': 6}, 9032: {'phone': 7}, 4660: {'phone': 8},
# 528: {'phone': 9}}

三丶线程池 threadpool模块

  可以模拟一个场景,假如我们要去领签名照,在工作室签名的明星只有两个在哪儿,而要领签名照的人很多很多,我们可以创建一个大纸箱子,把那些想要领签名照的人的信息记录下来,然后等明星按顺序来签名.这个大纸箱子就是我们所谓的线程池,存放一个个的需求等待CPU来调度

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)
import time
import threading def task(arg):
time.sleep(50) while True:
num = input('>>>')
t = threading.Thread(target=task,args=(num,))
t.start()

线程

import time
from concurrent.futures import ThreadPoolExecutor def task(arg):
time.sleep(10)
print("========") pool = ThreadPoolExecutor(3)
while True:
num = input('>>>')
pool.submit(task,num)

线程池

四丶生产者消费者模型

  所谓生产者消费者模型就是生产者跟消费者的关系而已,就像厨师跟顾客一样,只有厨师做出来饭,顾客才能吃,如果厨师做不出来饭,顾客想吃也吃不到,只能排队等

import time
import queue
import threading
q = queue.Queue() # 线程安全 def producer(id):
"""
生产者
:return:
"""
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):
"""
消费者
:return:
"""
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()

    

锁丶threading.local丶线程池丶生产者消费者模型的更多相关文章

  1. 线程锁、threading.local(flask源码中用的到)、线程池、生产者消费者模型

    一.线程锁 线程安全,多线程操作时,内部会让所有线程排队处理.如:list/dict/Queue 线程不安全 + 人(锁) => 排队处理 1.RLock/Lock:一次放一个 a.创建10个线 ...

  2. 锁、threading.local、线程池

    一.锁 Lock(1次放1个) 什么时候用到锁: 线程安全,多线程操作时,内部会让所有线程排队处理.如:list.dict.queue 线程不安全, import threading import t ...

  3. threading.local()方法;线程池

    一,threading.local() import time import threading v = threading.local() def func(arg): # 内部会为当前线程创建一个 ...

  4. 进程同步控制(锁,信号量,事件), 进程通讯(队列和管道,生产者消费者模型) 数据共享(进程池和mutiprocess.Pool模块)

    参考博客 https://www.cnblogs.com/xiao987334176/p/9025072.html#autoid-1-1-0 进程同步(multiprocess.Lock.Semaph ...

  5. 4、网络并发编程--僵尸进程、孤儿进程、守护进程、互斥锁、消息队列、IPC机制、生产者消费者模型、线程理论与实操

    昨日内容回顾 操作系统发展史 1.穿孔卡片 CPU利用率极低 2.联机批处理系统 CPU效率有所提升 3.脱机批处理系统 CPU效率极大提升(现代计算机雏形) 多道技术(单核CPU) 串行:多个任务依 ...

  6. python并发编程之多进程(二):互斥锁(同步锁)&进程其他属性&进程间通信(queue)&生产者消费者模型

    一,互斥锁,同步锁 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 竞争带来的结果就是错乱,如何控制,就是加锁处理 part1:多个进程共享同一打印终 ...

  7. Python之路(第三十八篇) 并发编程:进程同步锁/互斥锁、信号量、事件、队列、生产者消费者模型

    一.进程锁(同步锁/互斥锁) 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理. 例 ...

  8. python开发进程:互斥锁(同步锁)&进程其他属性&进程间通信(queue)&生产者消费者模型

    一,互斥锁,同步锁 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 竞争带来的结果就是错乱,如何控制,就是加锁处理 part1:多个进程共享同一打印终 ...

  9. java多线程:线程间通信——生产者消费者模型

    一.背景 && 定义 多线程环境下,只要有并发问题,就要保证数据的安全性,一般指的是通过 synchronized 来进行同步. 另一个问题是,多个线程之间如何协作呢? 我们看一个仓库 ...

  10. 基于线程实现的生产者消费者模型(Object.wait(),Object.notify()方法)

    需求背景 利用线程来模拟生产者和消费者模型 系统建模 这个系统涉及到三个角色,生产者,消费者,任务队列,三个角色之间的关系非常简单,生产者和消费者拥有一个任务队列的引用,生产者负责往队列中放置对象(i ...

随机推荐

  1. JSP相关背景

    -----------------siwuxie095                             Sun Microsystems             SUN 即 Stanford ...

  2. 第二周作业-影评、靶机和攻击机的安装与配置、kali的配置、DNS解析

    教材作业 第一章作业一 <黑客军团>第2季第1集影评 本文只分析与黑客攻击有关的情节,不谈其他. 开头,男主通过ssh以root身份远程连接到了一台服务器,并在其上执行了名为fuxsocy ...

  3. win7 失去焦点解决方案

    将HKEY_CURRENT_USER\Control Panel\Desktop中的ForegroundLockTimeout的选项,改成十进制的200000毫秒或者十六进制30d40. 参考链接: ...

  4. SQLServer数据库权限设置--保障数据库安全

    一.登陆界面引入 下图为SQL Server的登陆界面. 1)服务器名称:“.”代表本地计算机,选择下拉框,可以看见还有一个与本机机名相同的内容,也代表于本地服务器连接:要连接远程服务器的话,在此处填 ...

  5. Zookeeper安装和部署

    Zookeeper安装和部署:ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用 ...

  6. InfoQ —— 腾讯游戏大数据服务场景与应用

    简介 周东祥,本人从2010年毕业进入腾讯互动娱乐部门工作,一直致力在腾讯游戏运营开发工作.先后负责SAP业务受理系统,盗号自助系统,元数据系统以及近2年在腾讯游戏大数据运营开发中积累大量的大数据开发 ...

  7. springmvc ajax 简单例子

    1.控制器曾 @Controller public class AjaxController { @RequestMapping("/ajax") public void ajax ...

  8. myclipse运行web的一些问题

    一.修改项目访问路径 项目右键>properties(属性)>输入web搜索>双击web>修改Web-Content root内容即可 二. myeclipse中web项目不自 ...

  9. sql 存储过程-proc

    创建 create proc 存储过程名 (参数列表) as sql 语句 go 执行 exec 存储过程名 参数1,参数2 删除 drop procedure  存储过程名 注: 存储过程名最好以_ ...

  10. mac安装scrapy

    Mac自带python2.7,所以直接安装scrapy.默认安装了Xcode总共分以下几步:1.安装 homebrew.wget2.安装pip3.安装scrapy 安装homebrew在termina ...