Python中的线程详解
线程
常用的方法
import threading
import time
def hello(name):
print('Hello %s' % name)
# 阻塞
time.sleep(5)
print('阻塞了')
if __name__ == '__main__':
t1 = threading.Thread(target=hello, args=('zhangsan',))
t2 = threading.Thread(target=hello, args=('lisi',))
t1.setName('first') # 设置线程名
start = time.time()
t1.start()
t2.start()
print('---------------')
print(t1.getName())
end = time.time()
print(end-start) # 计算时间
运算的结果如下,可以看到遇到阻塞是直接进行了异步操作,先执行了所有的操作,然后才进行了等待操作,最后结束了程序

import threading
import time
def hello(name):
print('你好 %s' % name)
# 阻塞
time.sleep(5)
print('阻塞了')
if __name__ == '__main__':
t1 = threading.Thread(target=hello, args=('李',))
t2 = threading.Thread(target=hello, args=('王',))
t1.setName('aaa') # 设置线程名
start = time.time()
t1.start()
t2.start()
t2.join()
print('---------------')
print(t1.getName()) # 获取线程名字
end = time.time()
print(end-start) # 计算时间
运算结果如下:可以看到等待了5秒后才往后执行,join()方法让线程变的毫无意义。

继承类的线程使用方法
import threading
import time
class MyThread(threading.Thread):
def __init__(self, name):
super().__init__()
self.name = name
def run(self):
print('你好 %s' % self.name)
time.sleep(5)
print('阻塞了')
if __name__ == '__main__':
t1 = MyThread('李')
t2 = MyThread('王')
start = time.time()
t1.start()
t2.start()
end = time.time()
print('运行时间 %s 秒' % (end - start)) # 计算时间
计算结果如下所示:

守护进程 setDaemon
不开的状态
import threading
import time
def run(n):
print('你好 %s' % n)
time.sleep(2)
def main():
for i in range(5):
t = threading.Thread(target=run, args=(i,))
t.start()
m = threading.Thread(target=main)
m.start()
print('------运行结束-----')
运行结果:

开启后的状态
import threading
import time
def run(n):
print('你好 %s' % n)
time.sleep(2)
print('我随后跑')
def main():
for i in range(5):
t = threading.Thread(target=run, args=(i,))
t.start()
m = threading.Thread(target=main)
m.setDaemon(True) # 开启True将主线程设置为守护进程,主线程结束那一刻,其他子线程会同时结束,不论是否执行完毕
m.start()
print('------运行结束-----')
运行结果如下:
可以看到主进程结束,直接程序结束,子进程压根都没运行。这就是守护进程

线程锁Lock
一个进程下可以启动多个线程,多个线程共享父进程的内存空间,每个线程可以访问同一份数据,所以当多个线程同时要修改同一份数据时,就会出现错误。
import threading
import time
class MyThread(threading.Thread):
def run(self):
global num
time.sleep(1)
num = num + 1
msg = self.name + 'set num to' + str(num)
print(msg)
num = 0
def test():
for i in range(5):
t = MyThread()
t.start()
if __name__ == '__main__':
test()
运行结果出现了不可控,线程2没有增加到2,而线程5增加到了2,这是因为没有控制多个线程对同一资源的访问,对数据造成破坏,使得线程运行的结果不可预期。这种现象称为“线程不安全”。

加锁
创建锁
lock = threading.Lock()
锁定资源
lock.acquire()
释放资源
lock.release()
import threading
import time
class MyThread(threading.Thread):
def run(self):
global num
if lock.acquire():
time.sleep(1)
num = num + 1
msg = self.name + 'set num to' + str(num)
print(msg)
lock.release()
num = 0
lock = threading.Lock()
def test():
for i in range(5):
t = MyThread()
t.start()
if __name__ == '__main__':
test()
当多个线程都修改某一个共享数据的时候,需要进行同步控制。上锁之后,结果跟我们的预期完全一致。
互斥锁为资源引入一个状态:锁定/非锁定。某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。

递归锁RLock
锁中包含锁
import threading
def run1():
lock.acquire() # 小锁
global num
num += 1
lock.release()
return num
def run2():
lock.acquire() # 小锁
global num2
num2 += 1
lock.release()
return num2
def run3():
lock.acquire() # 大锁
res = run1()
res2 = run2()
lock.release()
print(res, res2)
if __name__ == '__main__':
num, num2 = 0, 0
lock = threading.RLock() # 生成Rlock
for i in range(10):
t = threading.Thread(target=run3)
t.start()
while threading.active_count() != 1: # 线程活动数量不是1,说明子线程还没运行完毕
pass
else:
print('运行结束')

semaphore信号量
同时允许一定数量的线程更改数据
import threading
import time
def run(n):
semaphore.acquire()
time.sleep(1)
print('run the thread: %s' % n)
semaphore.release()
if __name__ == '__main__':
semaphore = threading.BoundedSemaphore(3) # 设置最多允许3个线程同时运行
for i in range(20):
t = threading.Thread(target=run, args=(i,))
t.start()
3个3个分批次的出现

event事件
实现两个或多个线程间的交互
event.set() 会使event内部为真
event.clear() 会使event内部为假
event.isSet() 判断有没有被设定为真
如果event内部为真,则wait不阻塞,否则会阻塞
import threading
def start():
print('---start---1')
event.wait() # 阻塞
print('---start---2')
if __name__ == '__main__':
event = threading.Event()
t = threading.Thread(target=start)
t.start()
print(event.isSet())
运行结果,程序会阻塞在start1进行不下去

将event内部设置为真
import threading
def start():
print('---start---1')
event.wait() # 阻塞
print('---start---2')
if __name__ == '__main__':
event = threading.Event()
t = threading.Thread(target=start)
t.start()
event.set()
print(event.isSet())
运行结果会从阻塞变为畅通

Python中的线程详解的更多相关文章
- python中threading模块详解(一)
python中threading模块详解(一) 来源 http://blog.chinaunix.net/uid-27571599-id-3484048.html threading提供了一个比thr ...
- Python中time模块详解
Python中time模块详解 在平常的代码中,我们常常需要与时间打交道.在Python中,与时间处理有关的模块就包括:time,datetime以及calendar.这篇文章,主要讲解time模块. ...
- 第7.19节 Python中的抽象类详解:abstractmethod、abc与真实子类
第7.19节 Python中的抽象类详解:abstractmethod.abc与真实子类 一. 引言 前面相关的章节已经介绍过,Python中定义某种类型是以实现了该类型对应的协议为标准的,而不 ...
- python中常用模块详解二
log模块的讲解 Python 使用logging模块记录日志涉及四个主要类,使用官方文档中的概括最为合适: logger提供了应用程序可以直接使用的接口API: handler将(logger创建的 ...
- 76.Python中F表达式详解
F表达式是用来优化ORM操作数据库的. 举个例子:我们做口罩的公司要将所有员工的薪水增加2000元,如果按照正常的流程,应该是先从数据库中提取所有的员工的工资到Python内存中,然后使用Python ...
- python 中的unicode详解
通过例子来看问题是比较容易懂的. 首先来看,下面这个是我新建的一个txt文件,名字叫做ivan_utf8.txt,然后里面随便编辑了一些东西. 然后来用控制台打开这个文件,同样也是截图: 这里就是简单 ...
- Python中time模块详解(转)
在平常的代码中,我们常常需要与时间打交道.在Python中,与时间处理有关的模块就包括:time,datetime以及calendar.这篇文章,主要讲解time模块. 在开始之前,首先要说明这几点: ...
- python 中model.py详解
model详解 Django中遵循 Code Frist 的原则,即:根据代码中定义的类来自动生成数据库表. 创建表 基本结构 from django.db import models # Creat ...
- python 中的map 详解
python中的map函数应用于每一个可迭代的项,返回的是一个结果list.如果有其他的可迭代参数传进来,map函数则会把每一个参数都以相应的处理函数进行迭代处理.map()函数接收两个参数,一个是函 ...
随机推荐
- Python全栈之路----函数进阶----作用域的查找空间
n = 10 def func(): n = 20 print('func:',n) def func2(): n = 30 print('func2:',n) def func3(): print( ...
- 20155208徐子涵 Exp4 恶意代码分析
20155208徐子涵 Exp4 恶意代码分析 实践目标 1.1是监控你自己系统的运行状态,看有没有可疑的程序在运行. 1.2是分析一个恶意软件,就分析Exp2或Exp3中生成后门软件:分析工具尽量使 ...
- python 进程池的使用和坑
from multiprocessing import Pool,Process import time,os def Foo(a):#创建函数 time.sleep(2) print('in the ...
- PythonStudy——汇编语言 Assembly Language
汇编语言 汇编语言(assembly language)是一种用于电子计算机.微处理器.微控制器或其他可编程器件的低级语言,亦称为符号语言.在汇编语言中,用助记符(Mnemonics)代替机器指令的操 ...
- Java_框架面试题
Java_框架面试题 欢迎来我Git上分享您的优秀建议 1.Spring框架分为哪七大模块,各模块的主要功能作用是什么? 七大模块,如下: 1. Spring Core: Core封装包是框架的最基础 ...
- Kafka 配置安装
1.从官网下载安装包 http://kafka.apache.org/downloads2.上传到01虚拟机,解压3.进入安装目录下的config目录4.对server.properties进行配置 ...
- Vue自学笔记--项目的创建
一.项目的创建 1.必须要安装nodejs 2.搭建vue的开发环境 ,安装vue的脚手架工具 官方命令行工具 npm install --global vue-cli / ...
- Oracle 学习笔记(二)
一.索引 表的数据是无序的,所以叫堆表(heap table),意思为随机存储数据.因为数据是随机存储的,所以在查询的时候需要全表扫描.索引就是将无序的数据有序化,这样就可以在查询数据的时候 减少数据 ...
- scrollview嵌套recyclerview卡顿现象
方式一xml: android:nestedScrollingEnabled="false" <android.support.v7.widget.RecyclerView ...
- css学习1
1.标签的权值为1,类选择符的权值为10,ID选择符的权值最高为100 注意:还有一个权值比较特殊--继承也有权值但很低,有的文献提出它只有0.1,所以可以理解为继承的权值最低.