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 ...
随机推荐
- android SDK 无法更新
android-windows-sdk无法更新解决办法: 1.在host文件新增如下配置 (host文件位置:c:\Windows\System32\drivers\etc文件夹下面,用文本编辑器 ...
- spring boot 中使用 jpa以及jpa介绍
1.什么是jpa呢?JPA顾名思义就是Java Persistence API的意思,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中.12.jpa具有什么 ...
- SQLServer之修改FOREIGN KEY约束
使用SSMS数据库管理工具修改FOREIGN KEY约束 1.连接数据库,选择数据表->右键点击->选择设计(或者展开键,选择要修改的外键,右键点击,选择修改,后面修改步骤相同). 2.在 ...
- 同步锁Synchronized与Lock的区别?
synchronized与Lock两者区别: 1:Lock是一个接口,而Synchronized是关键字. 2:Synchronized会自动释放锁,而Lock必须手动释放锁. 3:Lock可以让等待 ...
- 黏包现象之TCP
老师的博客:http://www.cnblogs.com/Eva-J/articles/8244551.html#_label5 server #_*_coding:gbk*_ from socket ...
- 超哥笔记--shell 基本命令(4)
一 linux 命令行的组成结构 自定义命令行结构 PS1变量来控制 \u \W 最后一位工作目录 \w 绝对路径工作目录 \t 显示24h制的时间 \h PS1="[\u@\h \w \t ...
- 应用 memcached 提升站点性能
减少读自数据库和数据源 开源 memcached 工具是一个用来存储常用信息的缓存,有了它,您便无需从缓慢的资源,比如磁盘或数据库,加载(并处理)信息了.该工具可部署在专用的情况下,也可作为用完现有环 ...
- Error response from daemon: conflict: unable to remove repository reference 解决方案
由于前一章演示用的镜像没什么用准备删除 docker image rm hello-world:latest Error response from daemon: conflict: unable ...
- 转://诊断 Grid Infrastructure 启动问题 (文档 ID 1623340.1) .
文档内容 用途 适用范围 详细信息 启动顺序: 集群状态 问题 1: OHASD 无法启动 问题 2: OHASD Agents 未启动 问题 3: OCSSD.BI ...
- MyCP(课下作业,必做)
MyCP(课下作业,必做) 要求 编写MyCP.java 实现类似Linux下cp XXX1 XXX2 的功能,要求MyCP支持两个参数: java MyCP -tx XXX1.txt XXX2.bi ...