Python并行编程(三):线程同步之Lock
1、基础概念
当两个或以上对共享内存操作的并发线程中,如果有一个改变数据,又没有同步机制的条件下,就会产生竞争条件,可能会导致执行无效代码、bug等异常行为。
竞争条件最简单的解决方法是使用锁。锁的操作非常简单,当一个线程需要访问部分共享内存时,它必须先获得锁才能访问。此线程对这部分共享资源使用完成之后,释放锁,然后其他线程才可再次获得锁并访问这部分资源。
然而,在实际使用中,这个方法经常导致死锁现象。当不同线程要求得到同一个锁时,死锁就会发生,此时程序不会继续执行,因为他们互相拿着对方需要的锁。

造成死锁的原因:线程A在使用资源2,线程B在使用资源1,如果在没有释放锁时,线程A又需要资源1,线程B又需要资源2,但是两个资源的锁都是被占用的,而且在对方的锁释放之前都处于等待且不释放锁的状态,此时就会造成死锁。
使用锁来解决同步问题是一个可行的方式,但是也存在潜在的问题。
2、使用Lock进行线程同步
示例:
# coding : utf-8 import threading shared_resource_with_lock = 0
shared_resource_with_no_lock = 0
count = 100000 shared_resource_lock = threading.Lock() # has lock
def increment_with_lock():
global shared_resource_with_lock
for i in range(count):
shared_resource_lock.acquire()
shared_resource_with_lock += 1
shared_resource_lock.release()
def decrement_with_lock():
global shared_resource_with_lock
for i in range(count):
shared_resource_lock.acquire()
shared_resource_with_lock -= 1
shared_resource_lock.release() # has no lock
def increment_without_lock():
global shared_resource_with_no_lock
for i in range(count):
shared_resource_with_no_lock += 1 def decrement_without_lock():
global shared_resource_with_no_lock
for i in range(count):
shared_resource_with_no_lock -= 1 if __name__ == "__main__":
t1 = threading.Thread(target=increment_with_lock)
t2 = threading.Thread(target=decrement_with_lock)
t3 = threading.Thread(target=increment_without_lock)
t4 = threading.Thread(target=decrement_without_lock)
t1.start()
t2.start()
t3.start()
t4.start()
t1.join()
t2.join()
t3.join()
t4.join()
print("the value of shared with lock is %s" %shared_resource_with_lock)
print("the value of shared with no lock is %s" % shared_resource_with_no_lock)
执行结果:

在有锁的情况下,我们会得到挣钱的结果,而没有锁的情况下,往往会出现错误的结果。
3、锁状态
锁有两种状态:locked(被某一线程拿到)和unlocked(可用状态)
操作锁的方式:acquire()和release()
如果状态是unlocked,可以调用acquire将状态改为locked
如果状态是locked,acquire会被block直到另一个线程调用release释放锁
如果状态是unlocked,调用release会导致RuntimError异常
如果状态是locked,可以调用release将状态改为unlocked
Python并行编程(三):线程同步之Lock的更多相关文章
- Python并发编程-进程 线程 同步锁 线程死锁和递归锁
进程是最小的资源单位,线程是最小的执行单位 一.进程 进程:就是一个程序在一个数据集上的一次动态执行过程. 进程由三部分组成: 1.程序:我们编写的程序用来描述进程要完成哪些功能以及如何完成 2.数据 ...
- python网络编程基础(线程与进程、并行与并发、同步与异步、阻塞与非阻塞、CPU密集型与IO密集型)
python网络编程基础(线程与进程.并行与并发.同步与异步.阻塞与非阻塞.CPU密集型与IO密集型) 目录 线程与进程 并行与并发 同步与异步 阻塞与非阻塞 CPU密集型与IO密集型 线程与进程 进 ...
- .NET面试题解析(07)-多线程编程与线程同步
系列文章目录地址: .NET面试题解析(00)-开篇来谈谈面试 & 系列文章索引 关于线程的知识点其实是很多的,比如多线程编程.线程上下文.异步编程.线程同步构造.GUI的跨线程访问等等, ...
- .NET面试题解析(07)-多线程编程与线程同步 (转)
http://www.cnblogs.com/anding/p/5301754.html 系列文章目录地址: .NET面试题解析(00)-开篇来谈谈面试 & 系列文章索引 关于线程的知识点其实 ...
- python并发编程之线程/协程
python并发编程之线程/协程 part 4: 异步阻塞例子与生产者消费者模型 同步阻塞 调用函数必须等待结果\cpu没工作input sleep recv accept connect get 同 ...
- 《转载》Python并发编程之线程池/进程池--concurrent.futures模块
本文转载自Python并发编程之线程池/进程池--concurrent.futures模块 一.关于concurrent.futures模块 Python标准库为我们提供了threading和mult ...
- Python并行编程(五):线程同步之信号量
1.基本概念 信号量是由操作系统管理的一种抽象数据类型,用于在多线程中同步对共享资源的使用.本质上说,信号量是一个内部数据,用于标明当前的共享资源可以有多少并发读取. 同样在threading中,信号 ...
- Python并行编程(二):基于线程的并行
1.介绍 软件应用中使用最广泛的并行编程范例是多线程.通常一个应用有一个进程,分成多个独立的线程,并行运行.互相配合,执行不同类型的任务. 线程是独立的处理流程,可以和系统的其他线程并行或并发地执行. ...
- Python并行编程的几个要点
一.基于线程的并行编程 如何使用Python的线程模块 如何定义一个线程 如何探测一个线程 如何在一个子类中使用线程 Lock和RLock实现线程同步 信号实现线程同步 条件(condition)实现 ...
随机推荐
- 基于HTML5 Canvas 实现的 Loading 效果
Sonic.js 是一个很小的 JavaScript 类,用于创建基于 HTML5 画布的加载图像.更强大的是 Sonic.js 还提供了基于现成的例子的创建工具,可以帮助你实现更多自定义的(Load ...
- haproxy+keepalived实现高可用负载均衡(转)
软件负载均衡一般通过两种方式来实现:基于操作系统的软负载实现和基于第三方应用的软负载实现.LVS就是基于Linux操作系统实现的一种软负载,HAProxy就是开源的并且基于第三应用实现的软负载. ...
- Python之查询美国护照状态
该程序会每隔至少1秒进行一次护照状态查询 需要修改passportNo变量为自己的护照号码. 另外需要pip install beautifulsoup4 #coding=utf-8 import r ...
- Lifecycle for overriding binding, validation, etc,易于同其它View框架(Tiles等)无缝集成,采用IOC便于测试。
Lifecycle for overriding binding, validation, etc,易于同其它View框架(Tiles等)无缝集成,采用IOC便于测试. 它是一个典型的教科书式的mvc ...
- 【BZOJ】1047: [HAOI2007]理想的正方形(单调队列/~二维rmq+树状数组套树状数组)
http://www.lydsy.com/JudgeOnline/problem.php?id=1047 树状数组套树状数组真心没用QAQ....首先它不能修改..而不修改的可以用单调队列做掉,而且更 ...
- PyQt的QString 和 QStringList
在Qt的C++实现中的QString 和 QStringList 在Python的实现中等效替换为 "str1" 和 ["str1","str2&qu ...
- MongoDB基本用法
MongoDB基本用法(增删改高级查询.mapreduce) 分享一下我经常用到的自己写的mongo用法示例 该示例基于当前最新的mongo驱动,版本为mongo-2.10.1.jar,用junit写 ...
- VC中的学习点滴
1. __stdcall 和 __cdecl __cdecl 是C Declaration的缩写(declaration,声明),表示C语言默认的函数调用方法:所有参数从右到左依次入栈,由调用者负责 ...
- 学习《深入理解C#》—— 可空类型、可选参数和默认值 (第一章1.3)
目录 C#可空类型 C# 可选参数和默认值 C# 可空类型 在日常生活中,相信大家都离不开手机,低头族啊!哈哈... 假如手机厂商生产了一款新手机,暂时还未定价,在C#1中我们该怎么做呢? 常见的解决 ...
- 系统管理模块_用户管理1_实现用户有关的功能_测试功能、解决事务的问题、对密码进行MD5摘要
系统管理模块__用户管理1__实现用户有关的功能 了解用户管理要做什么(增删改查初始化密码) 设计实体 分析功能有几个对应几个请求 增删改查有6个请求,初始化密码一个 实现增删改查一组功能的步骤流程 ...