lock 机制不管你是java, C#, 还是python都是常用的线程同步机制, 相比较C# 的锁机制, python的加锁显得比较简单, 直接调用threading 标准库的lock 就可以了. python 的 lock类有两个函数, 分别是acquire 函数以及 release 函数, 前者起到锁定的作用, 将状态设置为锁定状态, 后者则是解锁, 将状态设置为未锁定状态. 我们看看代码:

# python 多线程同步  lock
import threading
from time import sleep num = 0
lock = threading.Lock() def func(st):
global num
print(threading.currentThread().getName() + ' try to acquire the lock')
if lock.acquire(): # 将状态修改为locked
print(threading.currentThread().getName() + ' acquire the lock.')
print(threading.currentThread().getName() + " :%s" % str(num))
num += 1
# sleep(st)
print(threading.currentThread().getName() + ' release the lock.')
lock.release() # 将状态修改为unlocked t1 = threading.Thread(target=func, args=(8,))
t2 = threading.Thread(target=func, args=(4,))
t3 = threading.Thread(target=func, args=(2,))
t1.start()
t2.start()
t3.start()

我们开了三个线程去调用同一个func 函数, 由于线程的不确定性, 如果没有加锁, 此时运行的话就会很混乱, 三个线程去执行同一个函数, 如果涉及到了变量的数据变化更是坑!因此我们加了锁, 确保数据的正确性, 函数执行的顺序性!

semaphore 信号量机制在python 里面也很简单就能够实现线程的同步。如果对操作系统有一定的了解, 那么对操作系统的PV原语操作应该有印象, 信号量其实就是基于这个机制的.semaphore 类是threading 模块下的一个类, 主要两个函数: acquire 函数, release 函数这和lock 类的函数是一样的, 只不过功能不一样, semaphore 机制的acquire 函数的参数允许你自己设置最大的并发量, 就是说允许多少个线程来操作同一个函数或是变量, 同时执行一次就会递减一次, release 函数则是递增, 如果计数到了0, 则阻塞起线程, 不再允许线程访问该方法或是变量.

# python 多线程同步   semaphore
import threading # 初始化信号量数量...当调用acquire 将数量置为 0, 将阻塞线程等待其他线程调用release() 函数
semaphore = threading.Semaphore(2) def func():
if semaphore.acquire():
for i in range(5):
print(threading.currentThread().getName() + ' get semaphore')
semaphore.release()
print(threading.currentThread().getName() + ' release semaphore') if __name__ == '__main__':
for i in range(4):
t1 = threading.Thread(target=func)
t1.start()

我们一次允许两个线程同时执行函数, 这可以从截图看出来:

event 机制不仅能够实现线程间的通信, 也是实现线程同步的一个好方法。事件是线程之间通信的最简单的机制之一, 一个线程指示一个事件和其他线程等待它.
event.py 是threading 模块下的一个类, 相比较前面两个机制, 这个类提供了四个方法, 分别是 is_set() 函数, set() 函数, clear() 函数, wait() 函数.
is_set判断事件管理标志是不是为true, 只有为true时, 才会返回
set 将标志设置为true
clear 将标志设置为flase
wait 等到标志为true时, 才会停止阻塞线程

import logging
import threading
import time # 打印线程名以及日志信息
logging.basicConfig(level=logging.DEBUG, format="(%(threadName)-10s : %(message)s", ) def wait_for_event_timeout(e, t):
"""Wait t seconds and then timeout"""
while not e.isSet():
logging.debug("wait_for_event_timeout starting")
event_is_set = e.wait(t) # 阻塞, 等待设置为true
logging.debug("event set: %s" % event_is_set)
if event_is_set:
logging.debug("processing event")
else:
logging.debug("doing other work") e = threading.Event() # 初始化为false
t2 = threading.Thread(name="nonblock", target=wait_for_event_timeout, args=(e, 2))
t2.start()
logging.debug("Waiting before calling Event.set()")
# time.sleep(7)
e.set() # 唤醒线程, 同时将event 设置为true
logging.debug("Event is set")

python lock, semaphore, event实现线程同步的更多相关文章

  1. python类库32[多进程同步Lock+Semaphore+Event]

    python类库32[多进程同步Lock+Semaphore+Event]   同步的方法基本与多线程相同. 1) Lock 当多个进程需要访问共享资源的时候,Lock可以用来避免访问的冲突. imp ...

  2. Python并行编程(三):线程同步之Lock

    1.基础概念 当两个或以上对共享内存操作的并发线程中,如果有一个改变数据,又没有同步机制的条件下,就会产生竞争条件,可能会导致执行无效代码.bug等异常行为. 竞争条件最简单的解决方法是使用锁.锁的操 ...

  3. Python多线程(2)——线程同步机制

    本文介绍Python中的线程同步对象,主要涉及 thread 和 threading 模块. threading 模块提供的线程同步原语包括:Lock.RLock.Condition.Event.Se ...

  4. Python并行编程(五):线程同步之信号量

    1.基本概念 信号量是由操作系统管理的一种抽象数据类型,用于在多线程中同步对共享资源的使用.本质上说,信号量是一个内部数据,用于标明当前的共享资源可以有多少并发读取. 同样在threading中,信号 ...

  5. [b0034] python 归纳 (十九)_线程同步_条件变量

    代码: # -*- coding: utf-8 -*- """ 学习线程同步,使用条件变量 逻辑: 生产消费者模型 一个有3个大小的产品库,一个生产者负责生产,一个消费者 ...

  6. [b0031] python 归纳 (十六)_线程同步_锁

    # -*- coding: utf-8 -*- """ 学习 多线程同步 使用锁 threading.Lock() 逻辑: 2 个线程,操作同一个整型变量,一个加法,另外 ...

  7. 线程高级应用-心得5-java5线程并发库中Lock和Condition实现线程同步通讯

    1.Lock相关知识介绍 好比我同时种了几块地的麦子,然后就等待收割.收割时,则是哪块先熟了,先收割哪块. 下面举一个面试题的例子来引出Lock缓存读写锁的案例,一个load()和get()方法返回值 ...

  8. Python并行编程(七):线程同步之事件

    1.基本概念 事件是线程之间用于通讯的对象.有的线程等待信号,有的线程发出信号.基本上事件对象都会维护一个内部变量,可以通过set方法设置为true,也可以通过clear方法设置为false.wait ...

  9. Python并行编程(四):线程同步之RLock

    1.基本概念 如果想让只有拿到锁的线程才能释放该锁,那么应该使用RLock()对象.当需要在类外面保证线程安全,又要在类内使用同样方法的时候RLock()就很使用. RLock叫做Reentrant ...

随机推荐

  1. 6.0、Android Studio性能优化工具

    显示图像包含四个步骤.简单来说,CPU对比显示列表,GPU渲染图片显示,内存存储图片和数据,电池提供点力能源.每个部分的硬件都有限制,超过这个限制会导致应用运行较慢,显示性能差,或者耗电. 为了查找造 ...

  2. Nhibernate系列学习之(一) ORM and Nhibernate入门实例解析

    最近框架项目需要,数据层想使用Nhibernate,代替传统的sql语句的写法,更加使用面向对象的思维来维护实体与数据库的这层关系映射(ORM),好在之前接触过Java时学习使用了Hibernate, ...

  3. Cocos2D瓦块地图高清屏(retina)显示比例问题的解决

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 在Cocos2D的游戏编程里,常用到瓦块地图.而cocos2D ...

  4. Dynamics CRM2015 2015版本可用的OData Query Designer工具

    2015后很多工具无法使用,包括2011版的OData Query Designer,这里介绍一款可用的工具,Dynamics XRM Tools for CRM 2015,下载地址:https:// ...

  5. Java-IO之PrintStream(打印输出流)

    PrintStream是打印输出流,继承于FilterOutputStream,PrintStream是用来装饰其他输出流,为其他输出流添加功能,方便他们打印出各种数据值表示形式.与其他输出流不同,P ...

  6. 一个Bootstrap的例子--关于validate

    </pre><pre name="code" class="html"><%@ page language="java& ...

  7. java中Error与Exception有什么区别

    Error类和Exception类都继承自Throwable类. Error的继承关系: java.lang.Object  java.lang.Throwable      java.lang.Er ...

  8. android sensor架构

    Android Sensor 架构深入剖析 作者:倪键树,华清远见嵌入式学院讲师. 1.Android sensor架构 Android4.0系统内置对传感器的支持达13种,它们分别是:加速度传感器 ...

  9. java控制台输入带空格的字符串

    java控制台输入带空格的字符串 Scanner sc = new Scanner(System.in); String str = sc.nextLine();

  10. 什么是IOC

    什么是IOC         IOC:控制反转,控制权的转移,应用程序本身不负责对象的创建和维护,而是由外部容器负责创建和维护.        DI(依赖注入)是其一种实现方式        目的:创 ...