Python:更新线程中的参数

2023-11-22

我想知道当该参数在程序主体中获得新值时是否可以启动一个新线程并更新其参数,所以像这样:

i = 0

def foo(i):
    print i
    time.sleep(5)

thread.start_new_thread(foo,(i,))

while True:
    i = i+1

非常感谢您的帮助!


与其他任何东西一样,参数只是一个值。传递该值只是对同一值进行新的引用,如果您改变该值,每个引用都会看到它。

全局变量和函数参数具有相同名称的事实与此无关,并且有点令人困惑,因此我将重命名其中一个。另外,你的foo函数仅能做到这一点print一次(可能在您增加值之前),然后休眠 5 秒,然后完成。你可能想要一个循环;否则,你实际上无法判断事情是否正常。

所以,这是一个例子:

i = []

def foo(j):
    while True:
        print j
        time.sleep(5)

thread.start_new_thread(foo,(i,))

while True:
    i.append(1)

那么,为什么你的代码不起作用?出色地,i = i+1不会改变值0,它正在分配一个new value, 0 + 1, to i. The foo函数仍然具有对旧值的引用,0,不变。

由于整数是不可变的,所以你不能directly解决这个问题。但是你可以间接地解决它很容易:用某种包装器替换整数is可变的。

例如,您可以编写一个 IntegerHolder 类set and get方法;当你i.set(i.get() + 1),另一个参考文献确实如此i.get(),它将看到新的值。

或者你可以只使用list作为持有者。列表是可变的,并且包含零个或多个元素。当你这样做时i[0] = i[0] + 1,这取代了i[0]具有新的整数值,但是i仍然是相同的列表值,这就是另一个引用所指向的。所以:

i = [0]

def foo(j):
    print j[0]
    time.sleep(5)

thread.start_new_thread(foo,(i,))

while True:
    i[0] = i[0]+1

这可能看起来有点hacky,但它实际上是一个非常常见的Python 习惯用法。


与此同时,事实是foo在另一个线程中运行会产生另一个问题。

理论上,线程同时运行,并且它们之间的任何数据访问没有顺序。您的主线程可能在核心 0 上运行,并处理i那是在 core 0 的缓存中,而你的foo线程正在核心 1 上运行,并在不同的副本上工作i它位于核心 1 的缓存中,并且代码中没有任何内容可以强制缓存同步。

在实践中,你经常会逃脱惩罚,尤其是在 CPython 中。但实际上know当你可以逃脱它时,你必须学习全局解释器锁是如何工作的,以及解释器如何处理变量,以及(在某些情况下)甚至你的平台的缓存一致性和你的C实现的内存模型等等如何工作。所以,你不应该依赖它。正确的做法是使用某种同步机制来保护对i.

作为旁注,你也不应该使用thread代替threading,所以我也将切换它。

i = []
lock = threading.Lock()

def foo(j):
    while True:
        with lock:
            print j[0]
        time.sleep(5)

t = threading.Thread(target=foo, args=(i,))
t.start()

while True:
    with lock:
        i[0] = i[0]+1

最后一件事:如果你创建一个线程,你需要join稍后再做,不然你就无法彻底退出。但你的foo线程永远不会退出,所以如果你尝试join它,你将永远被阻止。

对于像这样的简单情况,有一个简单的解决方案。致电之前t.start(), do t.daemon = True。这意味着当您的主线程退出时,后台线程将在任意时刻自动终止。如果要写入文件或数据库,这显然是一件坏事。但就你而言,它并没有做任何持久或危险的事情。

对于更实际的情况,您通常希望创建某种方式在两个线程之间发出信号。通常你已经有一些东西可以让线程等待——aQueue,一个文件对象或它们的集合(通过select)等。如果没有,只需创建一个受锁(或条件或任何适当的内容)保护的标志变量。

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

Python:更新线程中的参数 的相关文章

随机推荐

  • PostgreSQL:将非常大的数字的十六进制字符串转换为NUMERIC

    我正在尝试转换非常大的数字的十六进制字符串 到数字列 CREATE OR REPLACE FUNCTION hex to int hexval varchar RETURNS NUMERIC AS DECLARE result NUMERI
  • 使用 nls 在 R 中进行曲线拟合

    我正在尝试在以下数据 尾部 上拟合一条曲线 1 1 1 1 1 1 1 2 1 2 2 3 2 1 1 4 3 2 11 6 2 16 7 17 36 25 27 39 41 33 42 66 92 138 189 249 665 224
  • 检查会员/财产类型

    假设我有任何课程 比如这个 class SomeClass val aThing String val otherThing Double 然后我用反射来分析这个类的字段 for field in SomeClass declaredMem
  • 如何在 Node.JS 中限制(或排队)对外部进程的调用?

    Scenario 我有一个 Node JS 服务 使用编写ExpressJS 通过 DnD 接受图像上传 example 上传图像后 我对其执行一些操作 从中提取 EXIF 数据 调整大小 这些电话正在通过节点 imagemagick目前的
  • Chrome DevTools 扩展:如何从内容脚本中的元素面板中获取选定的元素?

    我已经完成了我的研究并为此苦苦挣扎了一段时间 但我需要你的帮助 我正在构建一个 Chrome DevTools 扩展 它应该传递 元素 面板中当前选定的元素作为参考到内容脚本中定义的 JS 对象 重要的是我要通过参考到选定的元素 或者从内容
  • 获取 64 位整数中的位位置数组

    好吧 这可能听起来有点复杂 但这就是我想要做的 以10101010101 并返回 0 2 4 6 8 10 包含所有已设置位的位置的数组 这是我的代码 UINT DQBitboard firstBit U64 bitboard static
  • jQuery:在模糊()事件之前触发单击()

    我有一个输入字段 我尝试在其中提出自动完成建议 代码看起来像
  • 如何在 Chrome 的弹出窗口上切换设备模式?

    我有一个网络应用程序 其中的聊天功能会在新的弹出窗口中打开 通常 在 Chrome 中我可以按 F12 并单击智能手机的图标来切换它 但在弹出的窗口中并没有出现该图标 这对我来说很重要 因为我需要限制弹出窗口的连接以模拟用户从聊天中断开连接
  • 如何在 GCC 中指定枚举大小?

    我想为枚举指定 64 位的枚举大小 这怎么可能通过 GCC 实现呢 该代码不需要 可移植 因为我只对使代码在 x86 32 和 x86 64 Linux 的 GCC 编译上工作感兴趣 这意味着任何可以提供我想要的功能的黑客都可以 只要它适用
  • 处理urllib2的超时? - Python

    我在 urllib2 的 urlopen 中使用超时参数 urllib2 urlopen http www example org timeout 1 我如何告诉Python 如果超时到期 应该引发自定义错误 有任何想法吗 您想要使用的情况
  • 为什么我的区域特定 Web API 可以从所有其他区域访问?

    我目前正在开发一个 ASP NET MVC 4 Web 应用程序项目 该项目必须遵守以下设计决策 主 MVC 应用程序位于解决方案的根目录中 所有管理员功能都位于单独的区域中 每个外部方 例如供应商 都有自己的区域 每个区域 包括根部 都构
  • 什么是 ruby​​ on Rails?

    我是一名前端开发人员 HTML CSS JS 和 jQuery 我了解一点 PHP 我正在尝试了解 Ruby Ruby on Rails 是什么 On http rubyonrails org 它说 Ruby on Rails 是一个开源
  • C++11 字符串开头的大小写不敏感比较(unicode)

    我必须检查特定字符串是否以另一个字符串开头 字符串使用 utf8 编码 比较应不区分大小写 我知道这与那个主题非常相似C 中不区分大小写的字符串比较但我不想使用 boost 库 我更喜欢便携式解决方案 如果 几乎 不可能 我更喜欢面向 Li
  • Angularjs 获取巨大 json 文件的请求

    我需要向用户显示数据库中的一些数据 数据位于 json 文件中 并且大小相当大 json 文件的大小大约在 15MB 左右 我创建了一个服务并使用 Promise api 发出成功的请求并加载数据并通过在 div 上执行 ng repeat
  • SFINAE 与以下 has_member 函数一起无法正常工作是什么?

    我正在尝试以下示例沃尔特 布朗 Walter Brown 的 TMP 演讲我正在努力得到他的has member实施工作 然而 实现似乎错误地返回 true 这让我相信 SFINAE 有一些我不理解的细节 include
  • 在 MATLAB 中使用 imshow 方法显示图像标题

    如何在 MATLAB 图形中显示图像标题 我有以下代码 I imread images pap png subplot 1 2 1 imshow I here I want to show labels Use the title命令 它的
  • 用于开发新的Windows Azure管理门户的框架?

    有谁知道微软使用什么框架在Windows Azure上开发类似Metro的Web管理门户 如果是这样 开发者可以使用吗 I 提出了同样的问题并因此受到很多仇恨 获胜的答案是地铁用户界面包 它完成了 Azure 中的许多工作 但您必须自己实现
  • 如何在 java 中使 JTable 可编辑

    我在 java 中使用 JTable 但它不允许我编辑单元格 private final TableModel dataModel new AbstractTableModel public int getColumnCount retur
  • proxyMode ScopedProxyMode.TARGET_CLASS 与 ScopedProxyMode.INTERFACE

    正如其他 SO 答案所建议的 根据您的需要使用代理模式类型 我仍然很困惑 Configuration ComponentScan public class Application public static void main String
  • Python:更新线程中的参数

    我想知道当该参数在程序主体中获得新值时是否可以启动一个新线程并更新其参数 所以像这样 i 0 def foo i print i time sleep 5 thread start new thread foo i while True i