我被Fyne(因此Go(的线程安全承诺所吸引。但是现在我越来越擅长阅读 Go,我看到的东西让人相信 API 作为一个整体不是线程安全的,也许从来没有打算过。所以我试图确定 Fyne 中的"线程安全"是什么意思。
我正在专门看
func (l *Label) SetText(text string) {
l.Text = text
l.textProvider.SetText(text) // calls refresh
}
并注意 l.Text 也是一个字符串。Go 中的赋值不是线程安全的,所以在我看来很明显,如果两个线程争夺标签的文本并且都调用标签。同时设置文本,我可以预期内存损坏。
"但你不会那样做",有人可能会说。不,但我担心有人编辑条目的内容,而应用程序线程决定需要替换所有条目的文本 - 这在我的应用程序中是完全可能的,因为它支持多个用户通过网络同时编辑,因此对各种小部件的更新都是异步的。(注意,我不在乎如果两个人同时编辑同一个条目会发生什么;某人的更改将丢失,我不在乎谁。但它不得导致内存损坏。请注意,我可以采取的一种方法是让后台线程创建一个全新的 Entry 小部件,然后替换当前 Box 中的小部件。但是这个线程安全吗?
不是我不知道如何用频道序列化东西。但我希望 Fyne 能够消除对它的需求(一篇博客文章声称它确实如此(;即使使用频道,我也无法说服自己,当某些后台线程更改它、隐藏它等时,用户以各种方式干预小部件不会导致崩溃。也许所有这些都是在幕后序列化的并且是完全安全的,但我不想发现它不是,因为我没有办法修复它。
Fyne显然是相当新的,似乎有很多希望,但文档似乎对细节很轻。是否有更多信息?人们成功尝试过吗?
您在此处找到了一些竞争条件。有改进的计划,但1.2版本需要首先获得新的"BaseWidget" - 这是几周前才发布的。
-
直接设置字段主要用于设置目的,因此不应以说明的方式使用。也就是说,我们确实希望支持它。基本小部件将很快引入类似于
SetFieldsAndRefresh(func())
的东西,这将确保传递的代码的安全性,并在之后刷新小部件。 -
目前
Refresh()
内确实有一场比赛。内部使用通道旨在消除这种情况 - 但有一些角落,例如多个 goroutines 调用它。这是我们新的 BaseWidget 代码可以帮助的领域 - 因为它们可以在内部自动锁定。使用此方法将是线程安全的,在将来的版本中不会对开发人员进行任何更改。
到目前为止,API 使开发人员不必担心线程并从任何 goroutines 工作 - 我们确实需要在内部工作以使其更安全 - 你说得很对。 https://github.com/fyne-io/fyne/issues/506