- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
两个线程之间的模糊锁定似乎与全局解释器锁或其他一些“幕后锁”有关,我不知道如何继续进行故障排除。任何有关如何消除锁定的提示都将不胜感激。
该问题在较大的一组代码中重现(不规律且有些随机)。代码是严格的python。 Python 版本为 2.6.5(在 Linux 上)。数小时的故障排除已将锁定发生时的问题减少到以下情况:
#5 中令人反感的调用是函数 unicode.encode,它应该是非阻塞的。线程 1 中线程锁将(如预期)打印“A”和“B”的位置的以下代码:
print('A')
print('B')
但是,下面的代码只会打印“A”并阻塞线程:
print('A')
u'hello'.encode('utf8') # This dummy (non-blocking) call locks up Thread 1
print('B')
这对我来说毫无意义。两个线程之间不存在逻辑死锁条件。线程 1 被非阻塞库调用阻塞,该库调用不会以任何方式干扰线程 2,线程 2 只是静静地等待获取 RLock。我能想到的线程 1 被阻塞的唯一原因是它正在等待 GIL。
有没有想过如何进一步解决这个问题,或者有什么机制可以以某种方式控制或操纵 GIL 操作作为解决方法?
编辑:针对样本偏差的一些额外信息(感谢您的回复)。我在跟踪时遇到了问题,因为这个问题似乎对任何可能扰乱两个线程之间的时间的事情都非常敏感。然而,仅使用 -f 选项运行 strace,经过几次迭代后,我能够获得跟踪。
线程 1 包含这三个调试语句,它们应该将两行“CHECK_IN”和“CHECK_TEST”打印到控制台:
print('CHECK IN')#DEBUG
u'hello'.encode('utf8')
print('CHECK TEST')#DEBUG
这是 strace 的最后一页:
8605 mmap2(NULL, 266240, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb753d000
8605 mmap2(NULL, 8392704, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0xb6d3c000
8605 mprotect(0xb6d3c000, 4096, PROT_NONE) = 0
8605 clone(child_stack=0xb753c494, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0xb753cbd8, {entry_number:6, base_addr:0xb753cb70, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}, child_tidptr=0xb753cbd8) = 8606
8606 set_robust_list(0xb753cbe0, 0xc <unfinished ...>
8605 futex(0xa239138, FUTEX_WAIT_PRIVATE, 0, NULL <unfinished ...>
8606 <... set_robust_list resumed> ) = 0
8606 futex(0xa239138, FUTEX_WAKE_PRIVATE, 1) = 1
8605 <... futex resumed> ) = 0
8606 gettimeofday( <unfinished ...>
8605 futex(0xa272398, FUTEX_WAIT_PRIVATE, 0, NULL <unfinished ...>
8606 <... gettimeofday resumed> {1301528807, 326496}, NULL) = 0
8606 futex(0xa272398, FUTEX_WAKE_PRIVATE, 1) = 1
8605 <... futex resumed> ) = 0
8606 futex(0xa272398, FUTEX_WAKE_PRIVATE, 1 <unfinished ...>
8605 gettimeofday( <unfinished ...>
8606 <... futex resumed> ) = 0
8605 <... gettimeofday resumed> {1301528807, 326821}, NULL) = 0
8606 futex(0xa272398, FUTEX_WAIT_PRIVATE, 0, NULL <unfinished ...>
8605 futex(0xa272398, FUTEX_WAKE_PRIVATE, 1 <unfinished ...>
8606 <... futex resumed> ) = -1 EAGAIN (Resource temporarily unavailable)
8605 <... futex resumed> ) = 0
8606 gettimeofday( <unfinished ...>
8605 futex(0xa272398, FUTEX_WAIT_PRIVATE, 0, NULL <unfinished ...>
8606 <... gettimeofday resumed> {1301528807, 326908}, NULL) = 0
8606 futex(0xa272398, FUTEX_WAKE_PRIVATE, 1) = 1
8605 <... futex resumed> ) = 0
8606 futex(0xa272398, FUTEX_WAKE_PRIVATE, 1 <unfinished ...>
8605 futex(0xa1b0d70, FUTEX_WAIT_PRIVATE, 0, NULL <unfinished ...>
8606 <... futex resumed> ) = 0
8606 stat64("/etc/localtime", {st_mode=S_IFREG|0644, st_size=2225, ...}) = 0
8606 fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
8606 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6d3b000
8606 write(1, "CHECK IN\n", 9) = 9
8606 futex(0xa115270, FUTEX_WAIT_PRIVATE, 0, NULL
在程序锁定之前,三行代码的输出如下:
CHECK IN
所以 strace 显示了线程 1 (#8606) 如何写入 'CHECK_IN' 字符串,以及当到达 unicode.encode 调用时进入永远不会返回的等待状态。
顺便说一句,我在所有模块中进行了一些 future 的导入,以保持一些更新的 python 约定......
from __future__ import print_function, unicode_literals
...但我看不出它们应该有什么不同 - 特别是当 u'hello' 字符串被显式调用为 unicode 字符串时。
最佳答案
我在 Python 源代码中找不到任何会导致 unicode.encode()
阻塞的内容,并且我编写的虚拟程序试图重现它按预期运行。您提到线程 1 已获得超过 1 个锁 - 您是否已将这些锁作为锁定源消除?
下面的测试用例是否在您的环境中显示了相同的锁定?
import time
import threading
def worker(tid):
_lock.acquire()
if not tid:
# wait for rest of threads to enter acquire
time.sleep(0.5)
print('%d: A' % tid)
u'hello'.encode('utf-8')
print('%d: B' % tid)
_lock.release()
def start(tid):
th = threading.Thread(target=worker, args=(tid,))
th.start()
return th
_num = 2
_lock = threading.RLock()
workers = [start(n) for n in range(_num)]
while all(w.isAlive() for w in workers):
time.sleep(1)
输出:
0: A
0: B
1: A
1: B
您还可以在您的程序上运行 strace
来找出进程被阻塞的位置。例如上面的脚本:
% strace -fTr -o trace.out python lockup.py
-o trace.out
标志告诉 strace 将输出写入文件。您可以省略它,strace 将打印到 stderr。
trace.out
的内容应该向您显示程序进行的所有系统调用,每行都以线程 ID 和系统调用之间的相对时间为前缀。该行的末尾将包含在该系统调用中花费的时间。我用相应的 Python 代码注释了最后几个系统调用:
# thread 0 time.sleep(0.5) completes
24778 0.500124 <... select resumed> ) = 0 (Timeout) <0.500599>
# preparing to print()
24778 0.000071 fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0 <0.000017>
24778 0.000058 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8fe90a6000 <0.000018>
# print("0: A\n")..
24778 0.000079 write(1, "0: A\n", 5) = 5 <0.000023>
24778 0.000106 write(1, "0: B\n", 5) = 5 <0.000056>
# thread 0 _lock.release()
24778 0.000114 futex(0xe0f3c0, FUTEX_WAKE_PRIVATE, 1) = 1 <0.000024>
24778 0.000108 madvise(0x7f8fe7266000, 8368128, MADV_DONTNEED) = 0 <0.000030>
# thread 0 exit
24778 0.000072 _exit(0) = ?
# thread 1 _lock.acquire()
24779 0.000050 <... futex resumed> ) = 0 <0.500774>
# thread 1 print("1: A\n") and so on..
24779 0.000052 write(1, "1: A\n", 5) = 5 <0.000026>
24779 0.000086 write(1, "1: B\n", 5) = 5 <0.000026>
24779 0.000099 madvise(0x7f8fe6a65000, 8368128, MADV_DONTNEED) = 0 <0.000024>
24779 0.000064 _exit(0) = ?
24777 0.499956 <... select resumed> ) = 0 (Timeout) <1.001138>
24777 0.000132 rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f8fe8c7c8f0}, {0x4d9a90, [], SA_RESTORER, 0x7f8fe8c7c8f0}, 8) = 0 <0.000025>
# main thread process exit
24777 0.002349 exit_group(0) = ?
关于python - 如何解决/绕过似乎与 GIL 相关的锁定问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5488257/
第一段代码工作正常,并给出了我需要的结果。我现在想做的是让它在 'as num' 上返回 3 个数字值对于“as num”上的 3 个不同值,对于同一列上的 3 个不同位置 SELEC
我想分析一些数据以编写定价算法。以下日期可用: 我需要三个变量/维度的函数/相关因子,它显示三个维度(pers_capacity、卧室数量、浴室数量)增长时中位数(价格)的变化。例如Y(#pers_c
正如标题所说 - 我的 Sprite Kit 游戏时不时地在后台崩溃,总是出现此错误 - Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Sub
假设我尝试保存以下数据,并且Songs模型的name属性上设置了Phalcon \ Mvc \ Model \ Validator \ PresenceOf验证器 // Get an existing
我有一个 if 控件,如下所示; if (Directory.Exists(System.IO.Path.Combine(systemPath, "Reports", companyName))
有人可以告诉我我们使用 ReadLine() 从文件 (.txt) 中读取特定行吗?现在我想读取文件的全部内容(不仅仅是第一行)。为此我需要使用什么方法。我用谷歌搜索了很多,但找不到解决方案。 我的代
我相信在大学时我用从 C 派生的语言为 FPGA 编写了一个程序。我了解 VHDL 和 verilog 等语言。但是,我不明白的是程序员在使用哪个方面有多少选择?它依赖于FPGA吗?我将使用 Xili
我有一个 if 控件,如下所示; if (Directory.Exists(System.IO.Path.Combine(systemPath, "Reports", companyName))
如何在运行时更改 Dashcode (Javascript) 中图像对象的源? 我试过: var image = document.getElementById("image").object;ima
我有几个相互关联的类,它们将被多种不同的算法使用 例子: struct B; struct A { B* parent; }; struct B { std::vector child
我正在开发一个网站,用户在客户收到的表中输入金额,如果任何客户没有提供分期付款(金额),则用户不会在表中输入任何金额,并且用户希望获取违约者的信息客户以10天为基础。所以我的问题是应该定义什么表和属性
我试图从上一个条目中选择一个值,并每次将该数字加一。我让它工作到选择当前条目值(默认 1000)并递增 1 并重新插入该值(因此每次最终都是 1001)。我需要它来选择该字段的最后一个条目,这样它将变
我不擅长“制作”查询。假设这是我的数据库: artist pics ------------------- -
最近,我要为我的网站做一个即时通知系统。我听说 COMET 在这种情况下必不可少。 我已经搜索 PHP 和 Comet 一段时间了,但是,我发现的指南和文章似乎只是循环中的 ajax 请求。例如,有一
我正在开发一款 iOS 游戏,我希望 clown 在场景外生成,然后向下移动。我的想法是全部创建它们,并将它们以 360 像素的距离放置在不可见的场景中。 像这样: SKSpriteNode *clo
我有以下子订单表。 mysql> select * from suborder; +-------------+------------------+ | order_state | bookin
这可能是一个有点初学者的问题,但考虑到在 Java 中调试编码是相当相关的:什么时候编码与 String 对象相关? 假设我有一个要保存到文件中的字符串对象。 String 对象本身是否使用某种我应该
首先我想说我是 CPP 的新手(我从 cpp11 开始):)考虑以下实体:学生(名字+姓氏)和组(描述+更多学生)。我在 C++ 中创建了以下 2 个类: class Student { privat
我正在尝试在单击该复选框时同步更新我的数据库。我决定使用 aJax,但它似乎无法识别 ajax。 代码:将成为 Switch_Active(this.id) 函数的元素 ... Deactivat
我正在创建一个菜单。菜单如下。 $('.category').mouseover(function() { $(this).removeClass('category').addClass('cate
我是一名优秀的程序员,十分优秀!