一、线程锁

  线程安全,多线程操作时,内部会让所有线程排队处理。如:list/dict/Queue

  线程不安全 + 人(锁) => 排队处理

1、RLock/Lock:一次放一个

  a、创建10个线程,在列表中追加自己,如下代码:

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

  b、创建10个线程,把自己添加到列表中,再读取列表的最后一个,如下代码:

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

  注意:RLock和Lock用法一样,只是Lock只能锁一次解一次,RLock支持锁多次解多次,以后用RLock。

2、BoundedSemaphore(n) ,信号量, 一次放n个,如下代码:

    import threading
import time lock = threading.BoundedSemaphore(3) def func(arg):
lock.acquire() # 加锁
time.sleep(1)
print(arg)
lock.release() # 释放锁 for i in range(10):
t = threading.Thread(target=func, args=(i,))
t.start()

3、condition(),一次放x个,x可由用户动态输入,代码如下:

  1)方式一:

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

  2)方式二:

    import time
import threading lock = threading.Condition()
def f1():
print('来执行函数了')
input(">>>")
return True def func(arg):
print('线程进来了')
lock.wait_for(f1) # 等函数f1执行完毕后继续往下走
print(arg)
time.sleep(1) for i in range(10):
t =threading.Thread(target=func,args=(i,))
t.start()

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

总结:

线程安全,列表和字典线程安全;

为什么要加锁?    非线程安全,控制一段代码;

二、threading.local()

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

    {

线程ID : { . . . },

线程ID : { . . . },

线程ID : { . . . },

线程ID : { . . . },

    }

    """
以后:Flask框架内部看到源码 上下文管理 """
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()

threading.local()的原理:

    import threading
import time v = threading.local() def func(arg):
v.phone = arg # 内部会为当前线程创建一个空间用于存储:phone = 自己的值
time.sleep(2)
print(v.phone,arg) # 去当前线程自己空间取值 for i in range(10):
t = threading.Thread(target=func, args=(i,))
t.start()

threading.local()的使用:

三、线程池

以后写代码不要一个一个创建线程,而是创建一个线程池,再去线程池申请线程去执行任务,如下示例:

    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)
四、生产者消费者模型

三部分:生产者,消费者,队列

队列:先进先出

栈:后进先出

  问题1:生产者消费者模型解决了什么问题?不用一直等待的问题。如下示例:

    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)
v = q.get()
print('顾客 %s 吃了一个%s' % (id,v)) for i in range(1,3):
t = threading.Thread(target=consumer,args=(i,))
t.start()

五、面向对象补充(了解,以后不会写,flask源码中会遇到)

    class Foo(object):
def __init__(self):
self.name = 'alex'
def __setattr__(self, key, value):
print(key,value)
obj = Foo() # 结果为:name alex (说明执行了Foo的__setattr__方法)
# 分析:因为obj.x自动执行__setattr__
print(obj.name) # 报错
# 分析:__setattr__方法中没有设置的操作,只有打印

示例一:

    class Foo(object):
def __init__(self):
object.__setattr__(self, 'info', {}) # 在对象中设置值的本质
def __setattr__(self, key, value):
self.info[key] = value
def __getattr__(self, item):
return self.info[item]
obj = Foo()
obj.name = 'alex'
print(obj.name)

示例二:

线程锁、threading.local(flask源码中用的到)、线程池、生产者消费者模型的更多相关文章

  1. 线程锁,threadinglocal,线程池,生产者消费者模型

    1.线程锁 1.锁Lock(只能锁一次) import threading import time v = [] lock = threading.Lock() def func(arg): lock ...

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

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

  3. 第23章 java线程通信——生产者/消费者模型案例

    第23章 java线程通信--生产者/消费者模型案例 1.案例: package com.rocco; /** * 生产者消费者问题,涉及到几个类 * 第一,这个问题本身就是一个类,即主类 * 第二, ...

  4. flask 源码专题(十一):LocalStack和Local对象实现栈的管理

    目录 04 LocalStack和Local对象实现栈的管理 1.源码入口 1. flask源码关于local的实现 2. flask源码关于localstack的实现 3. 总结 04 LocalS ...

  5. 04 flask源码剖析之LocalStack和Local对象实现栈的管理

    04 LocalStack和Local对象实现栈的管理 目录 04 LocalStack和Local对象实现栈的管理 1.源码入口 1. flask源码关于local的实现 2. flask源码关于l ...

  6. Flask源码关于local的实现

    flask源码关于local的实现 try: # 协程 from greenlet import getcurrent as get_ident except ImportError: try: fr ...

  7. 锁丶threading.local丶线程池丶生产者消费者模型

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

  8. 用尽洪荒之力学习Flask源码

    WSGIapp.run()werkzeug@app.route('/')ContextLocalLocalStackLocalProxyContext CreateStack pushStack po ...

  9. Flask 源码流程,上下文管理

    源码流程 创建对象 from flask import Flask """ 1 实例化对象 app """ app = Flask(__na ...

随机推荐

  1. node.js零基础详细教程(1):安装+基础概念

    第一章 建议学习时间2小时  课程共10章 学习方式:详细阅读,并手动实现相关代码 学习目标:此教程将教会大家 安装Node.搭建服务器.express.mysql.mongodb.编写后台业务逻辑. ...

  2. ExtjS学习--------Ext.define定义类

    Ext类Class的配置项:(注:Extjs的 的中文版帮助文档下载地址:http://download.csdn.net/detail/z1137730824/7748893 ExtJS配置文件和演 ...

  3. osx升级到10.10后,用pod install报错终于解决的方法

    先依照这个文章做:http://blog.csdn.net/dqjyong/article/details/37958067 大概过程例如以下: Open Xcode 6 Open Preferenc ...

  4. C++语言基础(12)-虚函数

    一.虚函数使用的注意事项 1.只需要在虚函数的声明处加上 virtual 关键字,函数定义处可以加也可以不加. 2.为了方便,你可以只将基类中的函数声明为虚函数,这样所有子类中具有遮蔽(覆盖)关系的同 ...

  5. 指尖上的电商---(11)Windows平台部署SolrCloud

    SolrCloud是一种分布式解决方式,是基于zookeeper和solr的,能够简单理解为一种集群,能够提供分布式查询.分布式写索引. SolrCloud的结构大致是这种,一个SolrCloud包含 ...

  6. IOS设计模式浅析之抽象工厂模式(Abstract Factory)

    概述 在前面两章中,分别介绍了简单工厂模式和工厂方法模式,我们知道简单工厂模式的优点是去除了客户端与具体产品的依赖,缺点是违反了“开放-关闭原则”:工厂方法模式克服了简单工厂模式的缺点,将产品的创建工 ...

  7. 椭圆曲线ECC基本概念

    椭圆曲线的曲线方程是以下形式的三次方程: y2+axy+by=x3+cx2+dx+e a,b,c,d,e是满足某些简单条件的实数.定义中包含一个称为无穷点的元素,记为O 如果其上的3个点位于同一直线上 ...

  8. redis 底层数据结构 压缩列表 ziplist

    压缩列表是列表键和哈希键的底层实现之一.当一个列表键只包含少量列表项,并且每个列表项要么就是小整数,要么就是长度比较短的字符串,redis就会使用压缩列表来做列表键的底层实现 当一个哈希键只包含少量键 ...

  9. selenium + js 处理窗口

    1.隐藏页面的广告窗口 document.getElementById("top_left").style.display="none"; 2.隐藏控件点击 d ...

  10. kafka 集群--3个broker 3个zookeeper创建实战

    准备工作: 1. 准备3台机器,IP地址分别为:192.168.0.10,192.168.0.11,192.168.0.12 2. 下载kafka稳定版本,我的版本为:kafka_2.9.2-0.8. ...