4

我知道XInitThreads()将允许我从主线程以外的线程调用 X 服务器,如果我想使用 Qt 从辅助线程进行 OpenGL 调用,Xlib 中的并发线程支持是必要的。我对我的应用程序有这样的需求,但在非常罕见的情况下。不幸的是,XInitThreads() 需要在我的应用程序执行的一开始就被调用,因此无论我是否需要它来进行特定的运行都会影响它(在我运行应用程序之前我无法知道我是否需要多线程 OpenGL支持与否)。

我很确定如果我无用地调用 XInitThread(),应用程序的整体行为将保持不变,但编程就是权衡取舍,我很确定多线程支持不是 Xlib 的默认行为是有原因的。

手册页说建议单线程程序不要调用此函数,但没有说明原因。调用 XInitThreads() 时的权衡是什么?

4

1 回答 1

13

它在每个显示器上创建一个全局锁,因此每次调用 Xlib 都会执行锁定/解锁。如果您改为进行自己的锁定(使用自己的锁一次将 Xlib 使用保持在单个线程中),那么理论上您可以通过获取锁定、一次执行大量 Xlib 内容然后丢弃来减少锁定开销你的锁。或者在实践中,大多数工具包使用的模型根本不锁定,只是要求应用程序仅在主 UI 线程中使用 X。

由于许多 Xlib 调用正在阻塞(它们等待来自服务器的回复),锁定争用可能是一个问题。

在 Display 上锁定 per-Xlib-call 也有一些语义上的痛苦;在线程 A 上的每个 Xlib 调用之间,理论上任何其他 Xlib 调用都可以在线程 B 上进行。因此线程可以在混淆显示状态方面相互踩踏,即使它们一次只有一个发出 Xlib 请求. 也就是说,XInitThreads() 正在防止由于并发显示访问而导致的崩溃/损坏,但它并没有真正考虑让多个线程共享 X 服务器连接的任何语义考虑。

我认为需要从并发显示访问中获得自己的语义意义是人们不关心 XInitThreads per-Xlib-call 锁定的原因之一。因为无论如何它们最终都会获得应用程序级别或工具包级别的锁。

这里的一种方法是在每个线程中打开一个单独的 Display 连接,这取决于你在做什么。

另一种方法是使用较新的 xcb API 而不是 Xlib;xcb 从头开始​​设计为多线程和非阻塞的。

从历史上看,在某些 OS/Xlib 版本中的 XInitThreads() 中也存在一些错误,尽管我不记得任何细节,但我记得看到那些过去了。

于 2012-11-13T13:59:21.410 回答