Python 之并发编程之线程中
四.线程锁lock(线程的数据安全)
在数据量较大的时候,线程中的数据会被并发,所有数据会不同步,以至于数据会异常。
下面还介绍了两种的上锁方法。
例:
from threading import Thread, Lock
import time
n = 0
def func1(lock):
global n
# time.sleep(0.3)
# print(11)
for i in range(10000):
# 正常上锁
lock.acquire()
print(n)
n -= 1
lock.release()
def func2(lock):
global n
# time.sleep(0.3)
# print(22)
for i in range(10000):
# 用with 自动上锁解锁
with lock:
print(n)
n += 1
if __name__ == "__main__":
# 创建一个锁
lock = Lock()
lst = []
for i in range(10):
t1 = Thread(target=func1, args=(lock,))
t2 = Thread(target=func2, args=(lock,))
t1.start()
t2.start()
lst.append(t1)
lst.append(t2)
for i in lst:
i.join()
print("主线程执行语句结束")
print(n) # n最后得0,如果没有加上锁的话,不会是0
# 程序执行结束
五.线程的信号量
例:效果是5个一打印,5个一打印
from threading import Semaphore, Thread
import time, random
def func(i, sem):
# with简写
with sem:
print(i)
time.sleep(random.uniform(0.1, 1))
"""
# 正常写法
sem.acquire()
print(i)
time.sleep(random.uniform(0.1,1))
sem.release()
"""
if __name__ == "__main__":
sem = Semaphore(5) # 设置几个线程同时运行几个
for i in range(50):
Thread(target=func, args=(i, sem)).start()
六.线程的锁
1.死锁
例:只有拿到筷子和面才能吃
noodle_lock = Lock()
chopsticks_lock = Lock()
def eat1(name):
noodle_lock.acquire()
print("%s拿到面条" % (name))
chopsticks_lock.acquire()
print("%s拿到筷子" % (name))
print("开始吃")
time.sleep(0.7)
chopsticks_lock.release()
print("%s放下筷子" % (name))
noodle_lock.release()
print("%s放下面条" % (name))
def eat2(name):
chopsticks_lock.acquire()
print("%s拿到筷子" % (name))
noodle_lock.acquire()
print("%s拿到面条" % (name))
print("开始吃")
time.sleep(0.6)
noodle_lock.release()
print("%s放下面条" % (name))
chopsticks_lock.release()
print("%s放下筷子" % (name))
if __name__ == "__main__":
name_list1 = ["one", "two"]
name_list2 = ["three", "four"]
for name in name_list1:
Thread(target=eat1, args=(name,)).start()
for name in name_list2:
Thread(target=eat2, args=(name,)).start()
# 双方都在等待,造成死锁的现象.
2.递归锁RLock
递归锁专门用来解决死锁现象
临时用于快速解决服务器崩溃的异常现象,用递归锁应急
解决应急问题的
(1)基本用法
from threading import Thread,RLock
# 递归锁如果3个,就对于释放3分锁,忽略上锁过程,进行解锁
rlock = RLock()
def func(name):
rlock.acquire()
print(name,1)
rlock.acquire()
print(name,2)
rlock.acquire()
print(name,3)
rlock.release()
rlock.release()
rlock.release()
lst = []
for i in range(10):
t1 = Thread(target=func,args=("name%s" % (i), ))
t1.start()
lst.append(t1)
for i in lst:
i.join()
print("程序结束了")
(2)用递归锁应急解决死锁现象
# 用递归锁应急解决死锁现象
noodle_lock = chopsticks_lock = RLock()
def eat1(name):
noodle_lock.acquire()
print("%s拿到面条" % (name))
chopsticks_lock.acquire()
print("%s拿到筷子" % (name))
print("开始吃")
time.sleep(0.7)
chopsticks_lock.release()
print("%s放下筷子" % (name))
noodle_lock.release()
print("%s放下面条" % (name))
def eat2(name):
chopsticks_lock.acquire()
print("%s拿到筷子" % (name))
noodle_lock.acquire()
print("%s拿到面条" % (name))
print("开始吃")
time.sleep(0.6)
noodle_lock.release()
print("%s放下面条" % (name))
chopsticks_lock.release()
print("%s放下筷子" % (name))
if __name__ == "__main__":
name_list1 = ["one", "two"]
name_list2 = ["three", "four"]
for name in name_list1:
Thread(target=eat1, args=(name,)).start()
for name in name_list2:
Thread(target=eat2, args=(name,)).start()
3.互斥锁
从语法上来看,锁是可以互相嵌套的,但是不要使用
上一次锁,就对应解开一把锁,形成互斥锁
吃面条和拿筷子是同时的,上一次锁就够了,不要分别上锁
尽量不要形成锁的嵌套,容易死锁
例:
from threading import Thread,RLock
mylock = Lock()
def eat1(name):
mylock.acquire()
print("%s拿到面条" % (name))
print("%s拿到筷子" % (name))
print("开始吃")
time.sleep(0.7)
print("%s放下筷子" % (name))
print("%s放下面条" % (name))
mylock.release()
def eat2(name):
mylock.acquire()
print("%s拿到筷子" % (name))
print("%s拿到面条" % (name))
print("开始吃")
time.sleep(0.6)
print("%s放下面条" % (name))
print("%s放下筷子" % (name))
mylock.release()
if __name__ == "__main__":
name_list1 = ["one", "two"]
name_list2 = ["three", "four"]
for name in name_list1:
Thread(target=eat1, args=(name,)).start()
for name in name_list2:
Thread(target=eat2, args=(name,)).start()
Python 之并发编程之线程中的更多相关文章
- Python并发编程之线程中的信息隔离(五)
大家好,并发编程 进入第三篇. 上班第一天,大家应该比较忙吧.小明也是呢,所以今天的内容也很少.只要几分钟就能学完. 昨天我们说,线程与线程之间要通过消息通信来控制程序的执行. 讲完了消息通信,今天就 ...
- Python 之并发编程之线程下
七.线程局部变量 多线程之间使用threading.local 对象用来存储数据,而其他线程不可见 实现多线程之间的数据隔离 本质上就是不同的线程使用这个对象时,为其创建一个只属于当前线程的字典 拿空 ...
- Python 之并发编程之线程上
一.线程概念 进程是资源分配的最小单位 线程是计算机中调度的最小单位 多线程(即多个控制线程)的概念是,在一个进程中存在多个控制线程,多个控制线程共享该进程的地址空间,相当于一个车间内有多条流水线,都 ...
- python 之 并发编程(线程Event、协程)
9.14 线程Event connect线程执行到event.wait()时开始等待,直到check线程执行event.set()后立即继续线程connect from threading impor ...
- Python 之并发编程之进程中(守护进程(daemon)、锁(Lock)、Semaphore(信号量))
五:守护进程 正常情况下,主进程默认等待子进程调用结束之后再结束守护进程在主进程所有代码执行完毕之后,自动终止kill -9 进程号 杀死进程.守护进程的语法:进程对象.daemon = True设置 ...
- python 之 并发编程(线程理论,开启线程的两种方式,进程与线程的区别,线程对象的其他方法)
9.9 线程理论 1.什么是线程 线程指的是一条流水线的工作过程 进程根本就不是一个执行单位,进程其实是一个资源单位,一个进程内自带一个线程,线程才是执行单位 2.进程VS线程 同一进程内的线程们共享 ...
- 《转载》Python并发编程之线程池/进程池--concurrent.futures模块
本文转载自Python并发编程之线程池/进程池--concurrent.futures模块 一.关于concurrent.futures模块 Python标准库为我们提供了threading和mult ...
- python并发编程之线程/协程
python并发编程之线程/协程 part 4: 异步阻塞例子与生产者消费者模型 同步阻塞 调用函数必须等待结果\cpu没工作input sleep recv accept connect get 同 ...
- Python 3 并发编程多进程之队列(推荐使用)
Python 3 并发编程多进程之队列(推荐使用) 进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的. 可以往 ...
随机推荐
- 「模板」AC自动机
目录 说明 普通版本 询问更改版 拓扑优化版本 说明 这篇博客只挂模板,具体分析请膜拜大佬 hyfhaha 大佬. 普通版本 题目传送门 #include<cstdio> #include ...
- buuctf 变异凯撒
加密密文:afZ_r9VYfScOeO_UL^RWUc 格式:flag{ } 这里我们发现a, f, Z, _的ASCii码是 97, 102, 90, 95 而再看这里flag{}的ASCii码是- ...
- Linux netstat命令详解(检验本机各端口的网络连接情况)
netstat命令用于显示与IP.TCP.UDP和ICMP协议相关的统计数据,一般用于检验本机各端口的网络连接情况.netstat是在内核中访问网络及相关信息的程序,它能提供TCP连接,TCP和UDP ...
- Logarithmic-Trigonometric积分系列(二)
\[\Large\displaystyle \int_0^{\pi/2}\ln^2(\sin x)\ln(\cos x)\tan x \,{\rm d}x\] \(\Large\mathbf{Solu ...
- 调用 flutter 第三方时间组件
https://pub.flutter-io.cn/packages/flutter_cupertino_date_picker flutter_cupertino_date_picker: ^1.0 ...
- sublime-text3 安装 emmet 插件
下载sublime,http://www.sublimetext.com/ 安装package control :https://packagecontrol.io/ins... 这个地址需要翻墙,访 ...
- Codeforces Round #577 (Div. 2) 题解
比赛链接:https://codeforc.es/contest/1201 A. Important Exam 题意:有\(n\)个人,每个人给出\(m\)个答案,每个答案都有一个分值\(a_i\), ...
- HGAME 2020 week1 web
1.Cosmos 的博客 知识点:git source code leak 2.接 头 霸 王 Description HGAME Re:Dive 开服啦~ 打开题目,提示了"头" ...
- python文件打开模式&time&python第三方库
r:以只读方式打开文件.文件的指针将会放在文件的开头.这是默认模式. w:打开一个文件只用于写入.如果该文件已存在则将其覆盖.如果该文件不存在,创建新文件. a:打开一个文件用于追加.如果该文件已存在 ...
- Exception in thread "main" java.lang.UnsupportedClassVersionError: org/apache/tools/ant/launch/Launcher : Unsupported major.min
有事这么一大串错误 1.版本问题 首先看咱们的jdk安装的版本,我装的是1.7.0,但是ant下的是1.10.0版本,换成1.7.0就ok了 官网下载http://ant.apache.org 所有版 ...