一、线程锁

  线程安全,多线程操作时,内部会让所有线程排队处理。如: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. 学习使用master.dbo.spt_values表

    如果要生成的临时表中有个连续的数字列,或者连续的日期列,如下所示: 2012-1-1 2012-1-2 2012-1-3 ... ... 可以这样写: declare @begin datetime, ...

  2. Rational Rose2007具体安装步骤

    学习了UML.那么Rational rose绘图软件当然就是不可缺少的了. 我的电脑是win7 64位的系统.以下的链接是安装软件以及破解方法.该软件是BIN格式的.也就是镜像文件.须要安装一个虚拟驱 ...

  3. silverlight 对ChildWindow返回给父窗体值的理解(转载)

    这篇文章是我对ChildWindow的理解,举例说明: 有时候在项目中需要弹出子窗体进行一些操作,然后将操作的值返回到父窗体中. 下图是子窗体的界面(比较粗糙....) 下面贴出其代码: 子窗体前台代 ...

  4. ../lib//libscsdblog.so: undefined reference to `pthread_atfork'

    代码中遇到这个问题,但是在makefile中已经添加了-lpthread. 最后发现问题时,引入库的顺序,把-lpthread放在最后就可以了.

  5. Blackey win10 + python3.6 + VSCode + tensorflow-gpu + keras + cuda8 + cuDN6N环境配置(转载)

    win10 + python3.6 + VSCode + tensorflow-gpu + keras + cuda8 + cuDN6N环境配置   写在前面的话: 再弄这个之前,我对python也好 ...

  6. PyTorch在64位Windows下的Conda包(转载)

    PyTorch在64位Windows下的Conda包 昨天发了一篇PyTorch在64位Windows下的编译过程的文章,有朋友觉得能不能发个包,这样就不用折腾了.于是,这个包就诞生了.感谢@晴天14 ...

  7. linux rz xshell

    这个命令写好好几次 就是没有记住 放到这里 每次用的时候查一遍 慢慢就记住了~~~ sudo yum install lrzsz -y

  8. python 面向对象三大特性(封装 多态 继承)

    今天我们来学习一种新的编程方式:面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)注:Java和C#来说只支持面向对象编程,而python比较灵活即支持面 ...

  9. 一个简单的servlet容器

    [0]README 0.1)本文部分文字转自 “深入剖析Tomcat”,旨在学习  一个简单的servlet容器  的基础知识: 0.2)for complete source code, pleas ...

  10. (转)Unity 导出XML配置文件,动态加载场景

    参考:http://www.xuanyusong.com/archives/1919 http://www.omuying.com/article/48.aspx   主要功能: 1.导出场景的配置文 ...