python 线程/线程锁/信号量
单线程
#常规写法 import threading
import time def sayhi(num): # 定义每个线程要运行的函数
print("running on number:%s" % num)
time.sleep() if __name__ == '__main__':
t1 = threading.Thread(target=sayhi, args=(,)) # 生成一个线程实例
t2 = threading.Thread(target=sayhi, args=(,)) # 生成另一个线程实例 t1.start() # 启动线程
t2.start() # 启动另一个线程 print(t1.getName()) # 获取线程名
print(t2.getName()) 自定义线程类
import threading
import time class MyThread(threading.Thread):
def __init__(self, num):
threading.Thread.__init__(self) self.num = num def run(self): # 定义每个线程要运行的函数
print("running on number:%s" % self.num)
time.sleep() if __name__ == '__main__':
t1 = MyThread()
t2 = MyThread() t1.start()
t2.start()
多线程
import threading
import time def sayhi(num): # 定义每个线程要运行的函数
print("running on number:%s" % num)
time.sleep() start_time=time.time()
if __name__ == '__main__':
for i in range(): ###多线程
t = threading.Thread(target=sayhi, args=(i,)) # 生成一个线程实例
t.start()
print (start_time-time.time()) ####打印时间 此时打印结果时间为0.0000几秒,是因为程序在执行完多线程时继续往下执行,而不会等待线程执行完在打印时间,所以打印出来的时间并不是多线程执行的时间 join()
线程执行后,主线程会等待所有线程执行完毕后继续往下走,下面实例介绍计算多线程执行时间 import threading
import time def sayhi(num): # 定义每个线程要运行的函数 print("running on number:%s" % num)
time.sleep() start_time=time.time() threads = [] ####定义一个列表,将所有的线程加进去
if __name__ == '__main__':
for i in range(): ###多线程
t = threading.Thread(target=sayhi, args=(i,)) # 生成一个线程实例
t.start()
threads.append(t) ####将每个线程添加到列表
for t in threads: ###循环整个列表,进行join(每个线程join完成后主线程才会继续往下走)
t.join() ###等待所有线程执行结束,相当于单线程 print (start_time-time.time())
示例二
#!/usr/bin/env python
#-*-coding:utf--*- import threading
from time import ctime,sleep
import time def music(func):
for i in range():
print ("Begin listening to %s. %s" %(func,ctime()))
sleep()
print("end listening %s"%ctime()) def move(func):
for i in range():
print ("Begin watching at the %s! %s" %(func,ctime()))
sleep()
print('end watching %s'%ctime()) threads = []
t1 = threading.Thread(target=music,args=('music',))
threads.append(t1)
t2 = threading.Thread(target=move,args=('movie',))
threads.append(t2) if __name__ == '__main__': for t in threads:
t.start()
print ("all over %s" %ctime())
守护线程
主线程不会等待守护线程结束在退出,会等待非守护线程执行完毕才退出
将线程设置为Daemon线程,它做为程序主线程的守护线程,当主线程退出时,线程也会退出,由守护线程动的其它子线程会同时退出,不管是否执行完任务
线程锁
由于线程之间是进行随机调度,并且每个线程可能只执行n条执行之后,当多个线程同时修改同一条数据时可能会出现脏数据,所以,出现了线程锁 - 即同一时刻允许一个线程执行操作
###没有加锁时 import threading
import time,sys def addNum():
global num # 在每个线程中都获取这个全局变量
print('--get num:', num)
time.sleep()
num -= # 对此公共变量进行-1操作 num = # 设定一个共享变量
thread_list = [] for i in range():
t = threading.Thread(target=addNum)
t.start()
thread_list.append(t)
for t in thread_list: # 等待所有线程执行完毕 t.join()
print('final num:', num) 说明:
正常来讲,这个num结果应该是0, 但在python 2.7上多运行几次,会发现,最后打印出来的num结果不总是0,为什么每次运行的结果不一样呢?
假设你有A,B两个线程,此时都 要对num 进行减1操作, 由于2个线程是并发同时运行的,所以2个线程很有可能同时拿走了num=100这个初始变量交给cpu去运算,当A线程去处完的结果是99,但此时B线程运算完的结果也是99,两个线程同时CPU运算的结果再赋值给num变量后,结果就都是99。那怎么办呢? 很简单,每个线程在要修改公共数据时,为了避免自己在还没改完的时候别人也来修改此数据,可以给这个数据加一把锁, 这样其它线程想修改此数据时就必须等待你修改完毕并把锁释放掉后才能再访问此数据。 加锁版本: import threading
import time gl_num =
lock = threading.RLock() ## 生成全局锁 def Func():
lock.acquire() #修改数据前加锁
global gl_num
gl_num +=
time.sleep()
print(gl_num)
lock.release() ###修改后释放 for i in range():
t = threading.Thread(target=Func)
t.start()
递归锁(即大锁之下在加小锁)
import threading, time def run1():
print("grab the first part data")
lock.acquire()
global num
num += 1
lock.release() return num def run2():
print("grab the second part data")
lock.acquire()
global num2
num2 += 1
lock.release() return num2 def run3():
lock.acquire()
res = run1()
print('--------between run1 and run2-----')
res2 = run2()
lock.release()
print(res, res2) if __name__ == '__main__':
num, num2 = 0, 0
lock = threading.RLock() for i in range(10):
t = threading.Thread(target=run3)
t.start() while threading.active_count() != 1:
print(threading.active_count()) else: print('----all threads done---')
print(num, num2)
条件变量同步(condition)
有一类线程需要满足条件之后才能够继续执行,Python提供了threading.Condition 对象用于条件变量线程的支持,它除了能提供RLock()或Lock()的方法外,还提供了 wait()、notify()、notifyAll()方法。
lock_con=threading.Condition([Lock/Rlock]): 锁是可选选项,不传人锁,对象自动创建一个RLock()。
wait():条件不满足时调用,线程会释放锁并进入等待阻塞;
notify():条件创造后调用,通知等待池激活一个线程;
notifyAll():条件创造后调用,通知等待池激活所有线程。
示例
import threading,time
from random import randint class Producer(threading.Thread):
def run(self):
global L
while True:
val=randint(0,100)
print('生产者',self.name,":Append"+str(val),L)
if lock_con.acquire():
L.append(val)
lock_con.notify()
lock_con.release()
time.sleep(3)
class Consumer(threading.Thread):
def run(self):
global L
while True:
lock_con.acquire()
if len(L)==0:
lock_con.wait()
print('消费者',self.name,":Delete"+str(L[0]),L)
del L[0]
lock_con.release()
time.sleep(0.25) if __name__=="__main__": L=[]
lock_con=threading.Condition()
threads=[]
for i in range(5):
threads.append(Producer())
threads.append(Consumer())
for t in threads:
t.start()
for t in threads:
t.join()
信号量
互斥锁,同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据 ,比如两个水龙头,那最多只允许2个人同时使用,后面的人只能等有人用完后才能使用。
信号量用来控制线程并发数的,BoundedSemaphore或Semaphore管理一个内置的计数 器,每当调用acquire()时-1,调用release()时+1。
计数器不能小于0,当计数器为 0时,acquire()将阻塞线程至同步锁定状态,直到其他线程调用release()。(类似于停车位的概念)
BoundedSemaphore与Semaphore的唯一区别在于前者将在调用release()时检查计数 器的值是否超过了计数器的初始值,如果超过了将抛出一个异常。
实例:
import threading, time def run(n):
semaphore.acquire()
time.sleep(1)
print("run the thread: %s" % n)
semaphore.release() if __name__ == '__main__':
num = 0
semaphore = threading.BoundedSemaphore(5) # 最多允许5个线程同时运行,有一个执行完毕后会执行另一个
for i in range(20):
t = threading.Thread(target=run, args=(i,))
t.start()
python 线程/线程锁/信号量的更多相关文章
- Python 线程同步锁, 信号量
同步锁 import time, threading def addNum(): global num num -= 1 num = 100 thread_list = [] for i in ran ...
- python 并发编程 锁 / 信号量 / 事件 / 队列(进程间通信(IPC)) /生产者消费者模式
(1)锁:进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的,而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理. 虽然使用加锁的形式实现了 ...
- {Python之线程} 一 背景知识 二 线程与进程的关系 三 线程的特点 四 线程的实际应用场景 五 内存中的线程 六 用户级线程和内核级线程(了解) 七 python与线程 八 Threading模块 九 锁 十 信号量 十一 事件Event 十二 条件Condition(了解) 十三 定时器
Python之线程 线程 本节目录 一 背景知识 二 线程与进程的关系 三 线程的特点 四 线程的实际应用场景 五 内存中的线程 六 用户级线程和内核级线程(了解) 七 python与线程 八 Thr ...
- Python的并发并行[1] -> 线程[2] -> 锁与信号量
锁与信号量 目录 添加线程锁 锁的本质 互斥锁与可重入锁 死锁的产生 锁的上下文管理 信号量与有界信号量 1 添加线程锁 由于多线程对资源的抢占顺序不同,可能会产生冲突,通过添加线程锁来对共有资源进行 ...
- Python之路(第四十四篇)线程同步锁、死锁、递归锁、信号量
在使用多线程的应用下,如何保证线程安全,以及线程之间的同步,或者访问共享变量等问题是十分棘手的问题,也是使用多线程下面临的问题,如果处理不好,会带来较严重的后果,使用python多线程中提供Lock ...
- Python进阶----线程基础,开启线程的方式(类和函数),线程VS进程,线程的方法,守护线程,详解互斥锁,递归锁,信号量
Python进阶----线程基础,开启线程的方式(类和函数),线程VS进程,线程的方法,守护线程,详解互斥锁,递归锁,信号量 一丶线程的理论知识 什么是线程: 1.线程是一堆指令,是操作系统调度 ...
- python 之 并发编程(守护线程与守护进程的区别、线程互斥锁、死锁现象与递归锁、信号量、GIL全局解释器锁)
9.94 守护线程与守护进程的区别 1.对主进程来说,运行完毕指的是主进程代码运行完毕2.对主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕详细解释:1.主 ...
- Python并发编程-进程 线程 同步锁 线程死锁和递归锁
进程是最小的资源单位,线程是最小的执行单位 一.进程 进程:就是一个程序在一个数据集上的一次动态执行过程. 进程由三部分组成: 1.程序:我们编写的程序用来描述进程要完成哪些功能以及如何完成 2.数据 ...
- 并发编程---线程 ;python中各种锁
一,概念 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个进程 --车间负责把资源整合到 ...
- 线程锁&信号量&gil
线程锁 线程锁的主要目的是防止多个线程之间出现同时抢同一个数据,这会造成数据的流失.线程锁的作用类似于进程锁,都是为了数据的安全性 下面,我将用代码来体现进程锁的作用: from threading ...
随机推荐
- LeetCode算法题-Perfect Number(Java实现)
这是悦乐书的第249次更新,第262篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第116题(顺位题号是507).我们定义Perfect Number是一个正整数,它等于 ...
- Eclipse编程中免除alt+斜杠,设置自动提示
用eclipse进行编程时,设置自动提示 .abcdefghijklmnopqrstuvwxyz@
- python 文件名的操作
1.文件操作 open()文件句柄:获取文件的路径信息 open() 打开一个文件,获取文件句柄 read() 全部读出出文件中的内容 readline() 读取文件中逐一读取一行数据 readlin ...
- java.io.IOException: There appears to be a gap in the edit log. We expected txid ***, but got txid
方式1 原因:namenode元数据被破坏,需要修复解决:恢复一下namenode hadoop namenode -recover 一路选择Y,一般就OK了 方式2 Need to copy the ...
- java.util.NoSuchElementException问题定位
Iterator 迭代器越界 例子如下: Iterator i = set.iterator(); while (i.hasNext()) { System.out.println(i.next()) ...
- web框架开发-Django模型层(2)-多表操作
很重要,都是精华 多表关系模型 一对一 一旦确定表关系是一对一,在两张表中的任意一张表中建立关联字段+Unique 一对多 一旦确定表关系是一对多,创建关联字段在多的表中 多对多 一旦确定表关系是多对 ...
- nodeJS之crypto模块md5和Hmac加密
nodeJS之crypto模块md5和Hmac加密 原文地址:https://www.cnblogs.com/tugenhua0707/p/9128690.html 在nodejs中,可以使用cryp ...
- 【jq】prop和attr的区别
prop()函数的结果: 1.如果有相应的属性,返回指定属性值. 2.如果没有相应的属性,返回值是空字符串. attr()函数的结果: 1.如果有相应的属性,返回指定属性值. 2.如果没有相应的属性, ...
- python 获取秒级时间间隔
import datetime,time start_tm=datetime.datetime.now() time.sleep() end_tm=datetime.datetime.now() pr ...
- 实现一个book类
设计实现一个book类 具体要求 定义义成Book.java,Book 包含书名,作者,出版社和出版日期,这些数据都要定义getter和setter. 定义至少三个构造方法,接收并初始化这些数据. 覆 ...