线程

常用的方法

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中的线程详解的更多相关文章

  1. python中threading模块详解(一)

    python中threading模块详解(一) 来源 http://blog.chinaunix.net/uid-27571599-id-3484048.html threading提供了一个比thr ...

  2. Python中time模块详解

    Python中time模块详解 在平常的代码中,我们常常需要与时间打交道.在Python中,与时间处理有关的模块就包括:time,datetime以及calendar.这篇文章,主要讲解time模块. ...

  3. 第7.19节 Python中的抽象类详解:abstractmethod、abc与真实子类

    第7.19节 Python中的抽象类详解:abstractmethod.abc与真实子类 一.    引言 前面相关的章节已经介绍过,Python中定义某种类型是以实现了该类型对应的协议为标准的,而不 ...

  4. python中常用模块详解二

    log模块的讲解 Python 使用logging模块记录日志涉及四个主要类,使用官方文档中的概括最为合适: logger提供了应用程序可以直接使用的接口API: handler将(logger创建的 ...

  5. 76.Python中F表达式详解

    F表达式是用来优化ORM操作数据库的. 举个例子:我们做口罩的公司要将所有员工的薪水增加2000元,如果按照正常的流程,应该是先从数据库中提取所有的员工的工资到Python内存中,然后使用Python ...

  6. python 中的unicode详解

    通过例子来看问题是比较容易懂的. 首先来看,下面这个是我新建的一个txt文件,名字叫做ivan_utf8.txt,然后里面随便编辑了一些东西. 然后来用控制台打开这个文件,同样也是截图: 这里就是简单 ...

  7. Python中time模块详解(转)

    在平常的代码中,我们常常需要与时间打交道.在Python中,与时间处理有关的模块就包括:time,datetime以及calendar.这篇文章,主要讲解time模块. 在开始之前,首先要说明这几点: ...

  8. python 中model.py详解

    model详解 Django中遵循 Code Frist 的原则,即:根据代码中定义的类来自动生成数据库表. 创建表 基本结构 from django.db import models # Creat ...

  9. python 中的map 详解

    python中的map函数应用于每一个可迭代的项,返回的是一个结果list.如果有其他的可迭代参数传进来,map函数则会把每一个参数都以相应的处理函数进行迭代处理.map()函数接收两个参数,一个是函 ...

随机推荐

  1. jquery绑定回车事件

    //回车事件绑定 $(".left-content").keyup(function(event){ var theEvent = event || window.event; v ...

  2. 使用maven profile指定配置文件打包适用多环境

    新建maven项目,   在pom.xml中添加 profile节点信息如下: <profiles> <profile> <!-- 开发环境 --> <id& ...

  3. MySQL:日期函数、时间函数总结(MySQL 5.X)

    http://www.cnblogs.com/she27/archive/2009/01/16/1377089.html 原文:http://www.51sdj.com/phpcms/picture/ ...

  4. LeetCode - Maximum Frequency Stack

    Implement FreqStack, a class which simulates the operation of a stack-like data structure. FreqStack ...

  5. selenium 网络请求

    selenium 网络请求 browser.find_element_by_id("id的name")browser.find_element("")brows ...

  6. git grep的一些用法

    https://www.kernel.org/pub/software/scm/git/docs/git-grep.html   把所有本地分支包含某个字符的行列出来,把含有master的列出来 gi ...

  7. Fabric的@runs_once的理解

    1:runs_once的用法,一直没理解,我看网上都是说:“函数修饰符,标识的函数只会执行一次,不受多台主机影响”     实在没理解,然后看了一下官方文档,这样解释     举个例子: #!/usr ...

  8. bootstrap弹出模态框会给body加padding的解决方法

    bootstrap弹出模态框会给body加padding,导致页面缩放的解决方法: 在页面或是css文件里加上($paddingSize为less变量,需要改成像素或是其他单位,如12px,1rem) ...

  9. oracle表被锁(delete或update一直处于执行状态)的处理办法。

    --首先查看有哪些锁 select /*+ rule */ s.username, decode(l.type,'TM','TABLE LOCK','TX','ROW LOCK',null) lock ...

  10. 【动态规划】最大连续子序列和,最大子矩阵和,最大m子段和

    1.最大字段和问题 求一个序列最大连续子序列之和. 例如序列[-1,-2,-3,4,5,-6]的最大子段和为4 + 5 = 9. ①枚举法 int MaxSum(int n,int *a){ int ...