【问题标题】:where is fyne's thread safety defined?fyne 的线程安全定义在哪里?
【发布时间】:2020-05-01 09:17:54
【问题描述】:

我被 Fyne(以及 Go)的线程安全承诺所吸引。但是现在我在阅读 Go 方面变得更好了,我看到一些事情让人相信 API 作为一个整体不是线程安全的,也许从来没有打算这样做。所以我试图确定 Fyne 中“线程安全”的含义。

我是专门看的

func (l *Label) SetText(text string) {
    l.Text = text
    l.textProvider.SetText(text) // calls refresh
}

并注意到 l.Text 也是一个字符串。 Go 中的赋值不是线程安全的,所以对我来说很明显,如果两个线程争夺标签的文本并且同时调用 label.SetText,我可以预料到内存损坏。

“但你不会那样做”,有人可能会说。不,但我担心有人编辑条目的内容,而应用程序线程决定它需要替换所有条目的文本 - 这在我的应用程序中是完全可能的,因为它支持多个用户通过网络同时编辑,所以各种小部件的更新都是异步的。 (注意我不关心如果两个人同时编辑同一个条目会发生什么;某人的更改将会丢失,我不在乎谁是。但它一定不会导致内存损坏。)请注意,我可以使用一种方法采取的做法是让后台线程创建一个全新的 Entry 小部件,然后替换当前 Box 中的那个。但是那个线程安全吗?

并不是我不知道如何用通道序列化东西。但我希望 Fyne 能够消除对它的需求(一篇博客文章声称它确实如此);即使使用频道,我也无法说服自己,当某个后台线程正在更改、隐藏它等时,用户以各种方式干预小部件不会导致崩溃。也许所有这些都在幕后序列化并且非常安全,但我不想找出它不是的困难方式,因为我无法修复它。

Fyne 显然是相当新的并且似乎有很多承诺,但文档似乎对细节很轻。是否有更多信息可以在某处获得?有人尝试过成功吗?

【问题讨论】:

  • 不熟悉 fyne - 但如果你是对的:如果两个 go-routines - 改掉在 go 中调用它们线程的习惯 - 如果两个 go-routines 调用 Label.SetText(...) 会有成为数据竞赛。但是我假设只有一个 UI 常规处理 UI 更新 - 这样可以避免任何争用。
  • 根据the bug tracker,有几个已知的数据竞争。显然,它们被视为错误,因此不是故意行为。
  • 是的 @colminator UI 更新是在单个线程上绘制的,但 API 旨在接受来自任何 goroutine 的更改。它还不是 100% 线程安全的,但将来应该会。
  • 文档目前在很多地方,应该尽快更新网站来解决这个问题。 fyne.io/developtour.fyne.io 是主要的地方。

标签: go thread-safety fyne


【解决方案1】:

您在这里找到了一些竞争条件。有改进计划,但 1.2 版本需要首先获得一个新的“BaseWidget”——而这只是在几周前发布的。

  1. 直接设置字段主要用于设置目的,因此不应以您说明的方式使用。也就是说,我们确实想支持它。基本小部件将很快引入类似于SetFieldsAndRefresh(func()) 的东西,这将确保传递代码的安全性并在之后刷新小部件。

  2. Refresh() 内当前确实有一场比赛。内部通道的使用旨在消除这一点 - 但有一些角落,例如多个 goroutine 调用它。这是我们新的 BaseWidget 代码可以提供帮助的区域 - 因为它们可以在内部自动锁定。使用这种方法将是线程安全的,在未来的版本中不会对开发人员进行任何更改。

到目前为止,API 使开发人员不必担心线程和任何 goroutine 的工作 - 我们确实需要在内部工作以使其更安全 - 你是对的。 https://github.com/fyne-io/fyne/issues/506

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-17
    • 2012-06-18
    • 1970-01-01
    相关资源
    最近更新 更多