线程执行

join与setDaemon

子线程在主线程运行结束后,会继续执行完,如果给子线程设置为守护线程(setDaemon=True),主线程运行结束子线程即结束;

如果join()线程,那么主线程会等待子线程执行完再执行。

 import threading
import time def get_thread_a():
print("get thread A started")
time.sleep(3)
print("get thread A end") def get_thread_b():
print("get thread B started")
time.sleep(5)
print("get thread B end") if __name__ == "__main__":
thread_a = threading.Thread(target=get_thread_a)
thread_b = threading.Thread(target=get_thread_b)
start_time = time.time()
thread_b.setDaemon(True)
thread_a.start()
thread_b.start()
thread_a.join() end_time = time.time()
print("execution time: {}".format(end_time - start_time))
thread_a是join,首先子线程thread_a执行,thread_b是守护线程,当主线程执行完后,thread_b不会再执行
执行结果如下:
get thread A started
get thread B started
get thread A end
execution time: 3.003199815750122

线程同步

当线程间共享全局变量,多个线程对该变量执行不同的操作时,该变量最终的结果可能是不确定的(每次线程执行后的结果不同),如:对count变量执行加减操作 ,count的值是不确定的,要想count的值是一个确定的需对线程执行的代码段加锁。

python对线程加锁主要有Lock和Rlock模块

Lock:

from threading import Lock

lock = Lock()
lock.acquire()
lock.release()

Lock有acquire()和release()方法,这两个方法必须是成对出现的,acquire()后面必须release()后才能再acquire(),否则会造成死锁

Rlock:

鉴于Lock可能会造成死锁的情况,RLock(可重入锁)对Lock进行了改进,RLock可以在同一个线程里面连续调用多次acquire(),但必须再执行相同次数的release()

from threading import RLock

lock = RLock()
lock.acquire()
lock.acquire()
lock.release()
lock.release()

condition(条件变量),线程在执行时,当满足了特定的条件后,才可以访问相关的数据

import threading

def get_thread_a(condition):
with condition:
condition.wait()
print("A : Hello B,that's ok")
condition.notify()
condition.wait()
print("A : I'm fine,and you?")
condition.notify()
condition.wait()
print("A : Nice to meet you")
condition.notify()
condition.wait()
print("A : That's all for today")
condition.notify() def get_thread_b(condition):
with condition:
print("B : Hi A, Let's start the conversation")
condition.notify()
condition.wait()
print("B : How are you")
condition.notify()
condition.wait()
print("B : I'm fine too")
condition.notify()
condition.wait()
print("B : Nice to meet you,too")
condition.notify()
condition.wait()
print("B : Oh,goodbye") if __name__ == "__main__":
condition = threading.Condition()
thread_a = threading.Thread(target=get_thread_a, args=(condition,))
thread_b = threading.Thread(target=get_thread_b, args=(condition,))
thread_a.start()
thread_b.start()

Condition内部有一把锁,默认是RLock,在调用wait()和notify()之前必须先调用acquire()获取这个锁,才能继续执行;当wait()和notify()执行完后,需调用release()释放这个锁,在执行with condition时,会先执行acquire(),with结束时,执行了release();所以condition有两层锁,最底层锁在调用wait()时会释放,同时会加一把锁到等待队列,等待notify()唤醒释放锁

wait() :允许等待某个条件变量的通知,notify()可唤醒

notify(): 唤醒等待队列wait()

执行结果:

B : Hi A, Let's start the conversation
A : Hello B,that's ok
B : How are you
A : I'm fine,and you?
B : I'm fine too
A : Nice to meet you
B : Nice to meet you,too
A : That's all for today
B : Oh,goodbye

Semaphore(信号量)

用于控制线程的并发数,如爬虫中请求次数过于频繁会被禁止ip,每次控制爬取网页的线程数量可在一定程度上防止ip被禁;文件读写中,控制写线程每次只有一个,读线程可多个。

import time
import threading def get_thread_a(semaphore,i):
time.sleep(1)
print("get thread : {}".format(i))
semaphore.release() def get_thread_b(semaphore):
for i in range(10):
semaphore.acquire()
thread_a = threading.Thread(target=get_thread_a, args=(semaphore,i))
thread_a.start() if __name__ == "__main__":
semaphore = threading.Semaphore(2)
thread_b = threading.Thread(target=get_thread_b, args=(semaphore,))
thread_b.start()

上述示例了每隔1秒并发两个线程执行的情况,当调用一次semaphore.acquire()时,Semaphore的数量就减1,直至Semaphore数量为0时被锁上,当release()后Semaphore数量加1。Semaphore在本质上是调用的Condition,semaphore.acquire()在Semaphore的值为0的条件下会调用Condition.wait(), 否则将值减1,semaphore.release()会将Semaphore的值加1,并调用Condition.notify()

Semaphore源码

def acquire(self, blocking=True, timeout=None):
if not blocking and timeout is not None:
raise ValueError("can't specify timeout for non-blocking acquire")
rc = False
endtime = None
with self._cond:
while self._value == 0:
if not blocking:
break
if timeout is not None:
if endtime is None:
endtime = _time() + timeout
else:
timeout = endtime - _time()
if timeout <= 0:
break
self._cond.wait(timeout)
else:
self._value -= 1
rc = True
return rc def release(self):
with self._cond:
self._value += 1
self._cond.notify()

Python线程同步的更多相关文章

  1. python线程同步原语--源码阅读

    前面两篇文章,写了python线程同步原语的基本应用.下面这篇文章主要是通过阅读源码来了解这几个类的内部原理和是怎么协同一起工作来实现python多线程的. 相关文章链接:python同步原语--线程 ...

  2. Python 线程同步

    #-*-coding:utf-8-*- '''如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性, 需要对多个线程进行同步. 线程同步所使用的的方法: Lock RLock ...

  3. Python 线程同步变量,同步条件,列队

    条件变量同步 有一类线程需要满足条件之后才能够继续执行,Python提供了threading.Condition 对象用于条件变量线程的支持,它除了能提供RLock()或Lock()的方法外,还提供了 ...

  4. Python 线程同步锁, 信号量

    同步锁 import time, threading def addNum(): global num num -= 1 num = 100 thread_list = [] for i in ran ...

  5. python——线程相关

    使用python的threading中的Thread 下面是两种基本的实现线程的方式: 第一种方式———— #coding=utf-8 """ thread的第一种声明及 ...

  6. python多线程同步机制Semaphore

    #!/usr/bin/env python # -*- coding: utf-8 -*- """ Python 线程同步机制:Semaphore "" ...

  7. Python多线程(2)——线程同步机制

    本文介绍Python中的线程同步对象,主要涉及 thread 和 threading 模块. threading 模块提供的线程同步原语包括:Lock.RLock.Condition.Event.Se ...

  8. PYTHON线程知识再研习E---条件变量同步Condition

    Python提供的Condition对象提供了对复杂线程同步问题的支持.Condition被称为条件变量,除了提供与Lock类似的 acquire和release方法外,还提供了wait和notify ...

  9. python lock, semaphore, event实现线程同步

    lock 机制不管你是java, C#, 还是python都是常用的线程同步机制, 相比较C# 的锁机制, python的加锁显得比较简单, 直接调用threading 标准库的lock 就可以了. ...

随机推荐

  1. VI编辑器、ipython、jupyter及进程知识总结

    一.VI编辑器 1.三种模式 一般模式(normal mode 默认) 插入模式(insert mode) 末行模式(last line mode) 2.模式切换 一般模式-------------- ...

  2. layui框架--关闭当前页面并刷新父页面

    //关闭当前页面 并刷新父页面 var index = parent.layer.getFrameIndex(window.name); parent.layer.close(index) windo ...

  3. 【MySql】Order By 排序

    你可以使用任何字段来作为排序的条件,从而返回排序后的查询结果. 你可以设定多个字段来排序. 你可以使用 ASC 或 DESC 关键字来设置查询结果是按升序或降序排列. 默认情况下,它是按升序排列. 你 ...

  4. Ubuntu16.04安装MySQL

      本篇教程在示例步骤中使用了以下版本的软件.操作时,请您以实际软件版本为准. 操作系统:Ubuntu 16.04.3 LTS (GNU/Linux 4.4.0-105-generic x86_64) ...

  5. 为 Confluence 6 分发包设置一个邮件会话

    最简单设置 Confluence 电子邮件发服务器的方否认就是通过 Confluence 的管理员控制台进行设置.请参考 Configuring a Server for Outgoing Mail ...

  6. python之属性描述符与属性查找规则

    描述符 import numbers class IntgerField: def __get__(self, isinstance, owner): print('获取age') return se ...

  7. BIgnum类的程序提交

    日期:2018.7.19 星期四 博客期:002 这之前赶着做一个单机游戏的修改器忘了时间,不好意思啊!今天我就把Bignum类的源代码发出来,文件的话,我不知道怎样发,待我好好研究研究这个网站哈!因 ...

  8. django模板 内建标签

    autoescape 控制当前自动转义的行为,有on和off两个选项 {% autoescape on %} {{ body }} {% endautoescape %} block 定义一个子模板可 ...

  9. SpringMVC环境搭建

    Spring MVC为展现层提供的基于MVC设计理念的优秀Web框架,是目前最主流的MVC框架之一. Spring 3.0之后完全超越Struts2,称为最优秀的MVC框架.学完SpringMVC之后 ...

  10. 剑指offer 二叉树中和为某一个值的路径

    剑指offer 牛客网 二叉树中和为某一个值的路径 # -*- coding: utf-8 -*- """ Created on Tue Apr 9 15:53:58 2 ...