线程

常用的方法

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. arduino uno r3的数据类型

    char 一个字节,存储一个字符值.字符文字用单引号写成:'A' unsigned char 无符号,一个字节 byte 一个字节,无符号数, int 2字节,这产生-32768至32767的范围. ...

  2. COMBIN14简单应用

    目录 案例1 说明 APDL代码 结果 案例2 说明 APDL代码 结果 案例3 说明 APDL代码 结果 参考网址:http://blog.sina.com.cn/s/blog_65936c2301 ...

  3. centos查看系统版本信息

    1.查看版本文件名称 ll /etc/*centos* 2.显示系统版本号 cat /etc/centos-release

  4. Linux之目录结构配置

    因为 Linux 的开发者实在太多了,如果每个人都发展出属于自己的目录配置方法, 那么将可能会造成很多管理上的困扰.所以,就有一个叫做Filesystem Hierarchy Standard (FH ...

  5. SSB基准测试

    SSB(Star Schema Benchmark)是麻省州立大学波士顿校区的研究人员定义的基于现实商业应用的数据模型,业界公认用来模拟决策支持类应用,比较公正和中立.学术界和工业界普遍采用它来评价决 ...

  6. DataTable.Select 处理关联表数据

    DataSet.Clone  会拷贝表结构,关联关系也会拷贝, 用Select 筛选后ImportRow 导入新的DataTable,然后处理关联DataTable DataSet ds2 = dsS ...

  7. ubuntu server资料

    2.改变键盘布局 sudo dpkg-reconfigure keyboard-configuration 或sudo vim /etc/default/keyboard,修改XKBLAYOUT变量的 ...

  8. PHP 获取数组是几维数组

    // 判断数组是几维数组$data = array(); // 是你要判断的数组$al = array(0);function aL($data,&$al,$level=0){ if(is_a ...

  9. python永久添加环境变量

    import sys sys.path 系统环境是一个list,可以将自己需要的库添加进入,例如mysql库,hive库等等.有三种方式添加,均验证通过:     1 临时添加,在一个shell窗口中 ...

  10. Linux中加速访问github

    1. 登录http://tool.chinaz.com/dns/ 2. 查询以下域名映射,并分别取访问速度较快的一个ip github.global.ssl.fastly.net   ->    ...