python 中的线程锁未按预期工作

2024-04-01

我试图保护线程内的数据免受主线程的影响。我有以下代码:

lock = threading.Lock()

def createstuff(data):
    t= threading.Thread(target=func, args=(data,))
    t.start()

def func(val):
    with lock:
        print 'acquired'
        time.sleep(2)
        print ('Value: %s, : %s'%(val, threading.currentThread().getName()))
        print 'released\n'

ags_list = ['x']

createstuff(ags_list)

rn =random.randint(5,50)
print 'random no:', rn
ags_list[0] = rn 

它产生输出:

acquired
random no: 10
Value: [10], : Thread-1
released

为什么更改主线程中的列表会导致另一个线程内的列表发生变化,即使它已被锁定?我可以做什么来预防它?谢谢。


因为只有当你在改变列表的任何地方都使用锁时,锁才会起作用,所以如果你只在一个地方调用它,它就不是一个在任何地方都有效的咒语。

要保护列表,您需要在两个线程上添加锁定上下文:

lock = threading.Lock()

def createstuff(data):
    t= threading.Thread(target=func, args=(data,))
    t.start()

def func(val):
    with lock:
        print 'thread: acquired'
        time.sleep(2)
        print ('Value: %s, : %s'%(val, threading.currentThread().getName()))
        print 'thread released'

ags_list = ['x']


createstuff(ags_list)

with lock:
    print 'thread: acquired'
    rn =random.randint(5,50)
    print 'random no:', rn
    ags_list[0] = rn 
    print 'thread: released'

您可以创建一个线程安全列表,例如:

class ThreadSafeList(list):
    def __init__(self, *args):
        super(ThreadSafeList, self).__init__(*args)
        self.lock = threading.Lock()
    def __setitem__(self, idx, value):
        with self.lock:
            print 'list acquired'
            super(ThreadSafeList, self)[idx] = value
            print 'list released'

然后使用它:

def createstuff(data):
    t= threading.Thread(target=func, args=(data,))
    t.start()

def func(val):
    time.sleep(2)
    print ('Value: %s, : %s'%(val, threading.currentThread().getName()))

args_list = ThreadSafeList(['x'])
createstuff(args_list)
rn =random.randint(5,50)
print 'random no:', rn
args_list[0] = rn 

当然这只是一个例子,还有待完善和完善。在这里我更愿意集中讨论这一点。

尽管您不需要在线程中锁定,因为从列表中访问值是(事实上)原子只读操作,因此列表的突变只能发生在列表中访问值之前或之后,而不是发生因为它正在访问该值。所以最终你的例子中不应该有任何种族问题。

如果您正在修改列表的值,或者对数据进行非原子访问,那么锁可能会很有用。

注意:如果您认为它可以以任何其他方式工作:互斥机制(通过实现Lock)不保护数据,它保护两个执行线程不同时执行。如果你断言锁定Thread A,在断言相同的锁之前Thread B, Thread B会等待Thread A解除锁定直到完成其工作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python 中的线程锁未按预期工作 的相关文章

  • 管理 Tweepy API 搜索

    如果这是对之前在其他地方回答过的问题的粗略重复 请原谅我 但我不知道如何使用 tweepy API 搜索功能 是否有任何有关如何使用搜索推文的文档api search 功能 有什么方法可以控制返回的推文数量 结果类型等功能 由于某种原因 结
  • 向 polls urls.py 添加额外的过滤器会导致测试失败

    按照 djangoproject 的教程 我尝试让 urls py 过滤掉没有选择下面 urlpattern 的民意调查 urlpatterns patterns url r ListView as view queryset Poll o
  • 如何使 Django ManyToMany “直通”查询更加高效?

    我使用的是 ManyToManyField 和 through 类 这会在获取事物列表时产生大量查询 我想知道是否有更有效的方法 例如 这里有一些描述书籍及其几位作者的简化类 它们通过角色类 定义 编辑器 插画家 等角色 class Per
  • 如何在不破坏默认行为的情况下覆盖 __getattr__ ?

    我如何覆盖 getattr https docs python org 3 reference datamodel html object getattr 类的方法而不破坏默认行为 压倒一切 getattr 应该没事 getattr 仅作为
  • 如何使用 boto3 从 AWS Cognito 获取经过身份验证的身份响应

    我想使用 boto3 获取访问 AWS 服务的临时凭证 用例是这样的 我的 Cognito 用户池中的用户登录到我的服务器 我希望服务器代码为该用户提供访问其他 AWS 服务的临时凭证 我有一个存储我的用户的 Cognito 用户池 我有一
  • Python pandas:删除字符串中分隔符之后的所有内容

    我有数据框 其中包含例如 vendor a ProductA vendor b ProductA vendor a Productb 我需要删除所有内容 包括 两个 以便我最终得到 vendor a vendor b vendor a 我尝
  • S3 选择检索 CSV 中的标头

    我尝试使用以下代码从存储在 S 存储桶中的 CSV 中获取记录子集 s3 boto3 client s3 bucket bucket file name file sql stmt SELECT S FROM s3object S LIMI
  • 将分布拟合到直方图

    I want to know the distribution of my data points so first I plotted the histogram of my data My histogram looks like th
  • 覆盖现有的 django-admin 命令

    除了编写自定义 django admin 命令之外 这是有详细记录的 https docs djangoproject com en 1 9 howto custom management commands 我希望能够覆盖现有命令 例如ma
  • C:如果文件描述符被删除,阻塞读取应该返回

    我正在以阻塞的方式从设备 文件描述符中读取 可能会发生这样的情况 在不同的线程中 设备被关闭并且文件描述符被删除 不幸的是 读取没有返回或注意到并且一直阻塞 作为一种解决方法 我可以使用 select 作为超时来执行 while 循环 如果
  • Bottle 是否可以处理没有并发的请求?

    起初 我认为 Bottle 会并发处理请求 所以我编写了如下测试代码 import json from bottle import Bottle run request response get post import time app B
  • PyPI 上的轮子平台约束有什么限制吗?

    是否有任何地方 PEP 或其他地方 声明关于 Linux 轮子上传范围的限制 PyPI http pypi io 应该有 具体来说 上传是否被认为是可接受的做法linux x86 64轮子到 PyPI 而不是manylinux1 x86 6
  • Python Flask应用程序无法被网络中的远程计算机访问

    我在本地主机上的 python 上运行了一个简单的 Flask Web 应用程序 Web 应用程序在 127 0 0 1 8000 上运行 但我无法使用 myHostComputerIPaddress 8000 从网络中的远程计算机访问它
  • Python `concurrent.futures`:根据完成顺序迭代 future

    我想要类似的东西executor map 除了当我迭代结果时 我想根据完成的顺序迭代它们 例如首先完成的工作项应该首先出现在迭代中 等等 这样 当且仅当序列中的每个工作项尚未完成时 迭代就会阻塞 我知道如何使用队列自己实现这一点 但我想知道
  • 使用 plone.api 创建文件的 Python 脚本在设置文件时出现错误 WrongType

    Dears 我正在创建一个脚本python来在Plone站点中批量上传文件 安装是UnifiedInstaller Plone 4 3 10 该脚本读取了一个txt 并且该txt以分号分隔 在新创建的项目中设置文件时出现错误 下面是脚本 f
  • 如何从外语线程调用Python函数(C++)

    我正在开发一个程序 使用 DirectShow 来抓取音频数据 媒体文件 DirectShow 使用线程将音频数据传递给回调 我的程序中的函数 然后我让该回调函数调用另一个函数 Python 中的函数 我使用 Boost Python 来包
  • Python中的MariaDB连接器无法连接到远程服务器

    我使用与远程 Mariadb 服务器的连接已有几个月了 今天 无法再通过 macOS 上的 python mariadb 模块和 mariadb 连接器建立连接 基本安装如下 brew install mariadb connector c
  • 在Python中打开网站框架或图像

    所以我对 python 相当熟练 并且经常使用 urllib2 和 Cookies 来实现网站自动化 我刚刚偶然发现了 webbrowser 模块 它可以在默认浏览器中打开一个网址 我想知道是否可以从该 url 中仅选择一个对象并打开它 具
  • Java,如何管理线程读取socket(websocket)?

    我有一个 WebSocket 服务器 我的服务器创建一个新线程来处理新连接 该线程一直处于活动状态 直到 websocket 中断 我的问题 对于 1 000 000 个连接 我需要 1 000 000 个线程 我如何通过一个线程处理多个
  • 将自定义属性添加到 Tk 小部件

    我的主要目标是向小部件添加隐藏标签或字符串之类的内容 以在其上保存简短信息 我想到创建一个新的自定义 Button 类 在本例中我需要按钮 它继承所有旧选项 这是代码 form tkinter import class NButton Bu

随机推荐