1. 线程通信

1.1 互斥锁

在多线程中 , 所有变量对于所有线程都是共享的 , 因此 , 线程之间共享数据最大的危险在于多个线程同时修改一个变量 , 那就乱套了 , 所以我们需要互斥锁 , 来锁住数据。

1.2 线程间全局变量的共享

注意:

因为线程属于同一个进程,因此它们之间共享内存区域。因此全局变量是公共的。

# -*- coding: utf-8 -*-
import threading
a = 1
def func():
    global  a
    a = 2
t = threading.Thread(target=func)
t.start()
t.join()
print(a)

1.3 共享内存间存在竞争问题

先来个正常的例子,不用多线程:

# -*- coding: utf-8 -*-
x = 0
n =1000000
def a(n):
    global x
    for i in range(n):
        x  = 1

def b(n):
    global x
    for i in range(n):
        x -= 1

a(n)
b(n)
print(x)

输出肯定和大家想的一样,毫无疑问是0!

# -*- coding: utf-8 -*-
from threading import Thread

x = 0
n =1000000
def a(n):
    global x
    for i in range(n):
        x  = 1

def b(n):
    global x
    for i in range(n):
        x -= 1

if __name__ == '__main__':
    a = Thread(target=a,args = (n,))
    b = Thread(target=b,args = (n,))
    a.start()
    b.start()
    # 一定要加阻塞,原因大家可以自己结合第一篇讲的自己好好想想哦~
    a.join()
    b.join()
    print(x)

提示:

  • 如果1000000不能出现效果可以继续在后面加0

你会发现这个结果千奇百怪!!!

1.4 使用锁来控制共享资源的访问

下面引入互斥锁

  • 在多线程中 , 所有变量对于所有线程都是共享的 ,因此 ,线程之间共享数据最大的危险在于多个线程同时修改一个变量 , 那就乱套了 , 所以我们需要互斥锁 , 来锁住数据
  • 只要我们操作全局变量的时候,就在操作之前加锁,在操作完之后解锁,就解决了这个资源竞争的问题!!!

第一种实现:

# -*- coding: utf-8 -*-
from threading import Thread, Lock

a = 0
n = 100000   # 指定加减次数
# 线程锁
lock = Lock()
def incr(n):
    global  a
    # 对全局变量a做n次加1
    for i in range(n):
        lock.acquire()
        a  = 1
        lock.release()
def decr(n):
    global a
    # 对全局变量a做n次减一
    for i in range(n):
        lock.acquire()
        a -= 1
        lock.release()
t_incr = Thread(target=incr, args=(n, ))
t_decr = Thread(target=decr, args=(n, ))
t_incr.start(); t_decr.start()
t_incr.join();  t_decr.join()
print(a)

第二种实现:

# -*- coding: utf-8 -*-
from threading import Thread, Lock

a = 0
n = 100000   # 指定加减次数
# 线程锁
lock = Lock()

def incr(n):
    global  a
    # 对全局变量a做n次加1
    for i in range(n):
        with lock:
            a  = 1
def decr(n):
    global a
    # 对全局变量a做n次减一
    for i in range(n):
        with lock:
            a -= 1

t_incr = Thread(target=incr, args=(n, ))
t_decr = Thread(target=decr, args=(n, ))
t_incr.start(); t_decr.start()
t_incr.join();  t_decr.join()
print(a)

分析此阶段,我们会发现进程和线程的痛点!!!

线程之间如何进行协作?

最典型的例子就是生产者/消费者模式:若干个生产者线程向队列中写入数据,若干个消费者线程从队列中消费数据。
(功能!)

  • 1.定义了一个生产者类,一个消费者类。
  • 2.生产者类循环100次,向同步队列当中插入数据。
  • 3.消费者循环监听同步队列,当队列有数据时拉取数据。
  • 4.如果队列满了(达到5个元素),生产者阻塞。
  • 5.如果队列空了,消费者阻塞。

    这里就引入了协程!是一种比线程更加轻量级的存在。正如一个进程可以拥有多个线程一样,一个线程也可以拥有多个协程。
最重要的是,协程不是被操作系统内核所管理,而完全是由程序所控制(也就是在用户态执行)。这样带来的好处就是性能得到了很大的提升,不会像线程切换那样消耗资源。

代码走起来(依旧是生产者/消费者模式的例子!):

def consumer():
    while True:
        # consumer协程等待接收数据
        number = yield
        print('开始消费', number)

consumer_result = consumer()
# 让初始化状态的consumer协程先执行起来,在yield处停止
next(consumer_result)

for num in range(100):
    print('开始生产', num)
    # 发送数据给consumer协程
    consumer_result.send(num)

代码中创建了一个叫做consumer_result的协程,并且在主线程中生产数据,协程中消费数据。
其中 yield 是python当中的语法。当协程执行到yield关键字时,会暂停在那一行,等到主线程调用send方法发送了数据,协程才会接到数据继续执行。
但是,yield让协程暂停,和线程的阻塞是有本质区别的。协程的暂停完全由程序控制,线程的阻塞状态是由操作系统内核来进行切换。

因此,协程的开销远远小于线程的开销!!!

执行结果:

2. 队列的基本概念

  • 一个入口,一个出口;
  • 先入先出(FIFO)。

import queue

队列操作一览:

  • 入队: put(item)
  • 出队: get()
  • 测试空: empty()
  • 测试满: full()
  • 队列长度: qsize()
  • 任务结束: task_done()
  • 等待完成: join()

注意:

  • get()等待任务完成,如果不加task_done()则不表示任务完成,只要加这句才表明完成。才会结束执行。
  • join就是阻塞,直到这个任务完成(完成的标准就是每次取出都task_done()了)

简单使用队列的方法:

# -*- coding: utf-8 -*-
import queue

# 创建队列
q = queue.Queue(4)

# 入队
q.put(1)
q.put(2)
q.put(3)
print(q.full())
q.put(4)
print(q.full())

# 出队
print(q.get())
print(q.get())
print(q.empty())
print(q.get())
print(q.get())
print(q.empty())

总结

到此这篇关于Python常用模块之threading和Thread模块及线程通信的文章就介绍到这了,更多相关Python 线程通信内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

Python常用模块之threading和Thread模块及线程通信的更多相关文章

  1. 详解html5 postMessage解决跨域通信的问题

    这篇文章主要介绍了详解html5 postMessage解决跨域通信的问题的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. 详解使用postMessage解决iframe跨域通信问题

    这篇文章主要介绍了详解使用postMessage解决iframe跨域通信问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  3. HTML5调用手机发短信和打电话功能

    这篇文章主要介绍了HTML5调用手机发短信和打电话功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  4. 真正的iOS设备和Watch Simulator可以进行通信以进行测试

    我想为现有的iOS应用创建一个手表应用.但我处于一种情况,我没有苹果手表,我现有的iOS应用程序只能在不在模拟器上的真实设备上运行.是否可以在iPhone设备上运行应用程序并在手表模拟器中测试我的手表应用程序?解决方法至少在目前,不可能配对真正的iPhone和Watch模拟器.我得出这个结论有三个原因:>Watch模拟器在安装过程中自动与iPhone模拟器配对.>根本无法从界面取消配对Watch模拟器.>在模拟器上无法访问蓝牙以与真实设备进行通信.这是一个proof.

  5. iOS:核心图像和多线程应用程序

    我试图以最有效的方式运行一些核心图像过滤器.试图避免内存警告和崩溃,这是我在渲染大图像时得到的.我正在看Apple的核心图像编程指南.关于多线程,它说:“每个线程必须创建自己的CIFilter对象.否则,你的应用程序可能会出现意外行为.”这是什么意思?我实际上是试图在后台线程上运行我的过滤器,所以我可以在主线程上运行HUD(见下文).这在coreImage的上下文中是否有意义?

  6. ios – 多个NSPersistentStoreCoordinator实例可以连接到同一个底层SQLite持久性存储吗?

    我读过的关于在多个线程上使用CoreData的所有内容都讨论了使用共享单个NSPersistentStoreCoordinator的多个NSManagedobjectContext实例.这是理解的,我已经使它在一个应用程序中工作,该应用程序在主线程上使用CoreData来支持UI,并且具有可能需要一段时间才能运行的后台获取操作.问题是NSPersistentStoreCoordinator会对基础

  7. ios – XCode断点应该只挂起当前线程

    我需要调试多线程错误.因此,为了获得生成崩溃的条件,我需要在代码中的特定点停止一个线程,并等待另一个线程到达第二个断点.我现在遇到的问题是,如果一个线程遇到断点,则所有其他线程都被挂起.有没有办法只停止一个线程,让其他线程运行,直到它们到达第二个断点?)其他更有趣的选择:当你点击第一个断点时,你可以进入控制台并写入这应该在该断点处暂停当前上下文中的线程一小时.然后在Xcode中恢复执行.

  8. ios – 如何使用iphone使用蓝牙或wifi与OBD II进行通信

    我想为iOS创建一个简单的应用程序,它通过ODBIIWifi/蓝牙设备从汽车读取数据并在iPhone屏幕上显示.但我不知道从哪里开始.请有人帮我实现以下结果.我有蓝牙和wifi加密狗.第1步:配对蓝牙或Wifi加密狗和iPhone.第2步:通过加密狗阅读详细信息请参阅我能够轻松理解的任何教程或示例代码.我想深入了解这些过程,并希望自己编写代码.所以请帮忙.提前致谢.解决方法正如David所说,在i

  9. ios – 在后台线程中写入Realm后,主线程看不到更新的数据

    >清除数据库.>进行API调用以获取新数据.>将从API检索到的数据写入后台线程中的数据库中.>从主线程上的数据库中读取数据并渲染UI.在步骤4中,数据应该是最新数据,但我们没有看到任何数据.解决方法具有runloops的线程上的Realm实例,例如主线程,updatetothelatestversionofthedataintheRealmfile,因为通知被发布到其线程的runloop.在后台

  10. ios – Arduino和iPhone与蓝牙3.0的连接

    我想构建一个需要蓝牙连接的应用程序.蓝牙HC05模块连接到Arduino.我想知道构建可连接到此蓝牙模块的应用程序所需的框架.仍然不知道如何开始.有人可以帮忙吗?

随机推荐

  1. 10 个Python中Pip的使用技巧分享

    众所周知,pip 可以安装、更新、卸载 Python 的第三方库,非常方便。本文小编为大家总结了Python中Pip的使用技巧,需要的可以参考一下

  2. python数学建模之三大模型与十大常用算法详情

    这篇文章主要介绍了python数学建模之三大模型与十大常用算法详情,文章围绕主题展开详细的内容介绍,具有一定的参考价值,感想取得小伙伴可以参考一下

  3. Python爬取奶茶店数据分析哪家最好喝以及性价比

    这篇文章主要介绍了用Python告诉你奶茶哪家最好喝性价比最高,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧

  4. 使用pyinstaller打包.exe文件的详细教程

    PyInstaller是一个跨平台的Python应用打包工具,能够把 Python 脚本及其所在的 Python 解释器打包成可执行文件,下面这篇文章主要给大家介绍了关于使用pyinstaller打包.exe文件的相关资料,需要的朋友可以参考下

  5. 基于Python实现射击小游戏的制作

    这篇文章主要介绍了如何利用Python制作一个自己专属的第一人称射击小游戏,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起动手试一试

  6. Python list append方法之给列表追加元素

    这篇文章主要介绍了Python list append方法如何给列表追加元素,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  7. Pytest+Request+Allure+Jenkins实现接口自动化

    这篇文章介绍了Pytest+Request+Allure+Jenkins实现接口自动化的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  8. 利用python实现简单的情感分析实例教程

    商品评论挖掘、电影推荐、股市预测……情感分析大有用武之地,下面这篇文章主要给大家介绍了关于利用python实现简单的情感分析的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下

  9. 利用Python上传日志并监控告警的方法详解

    这篇文章将详细为大家介绍如何通过阿里云日志服务搭建一套通过Python上传日志、配置日志告警的监控服务,感兴趣的小伙伴可以了解一下

  10. Pycharm中运行程序在Python console中执行,不是直接Run问题

    这篇文章主要介绍了Pycharm中运行程序在Python console中执行,不是直接Run问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

返回
顶部