有没有可能以某种简单的方式来实现Java的
wait(long timeMillis)
字符串
它会在一个监视器上等待一段指定的时间(大概是mutex+cond),如果没有收到信号就返回?
我在文档或谷歌上找不到任何关于这一点的东西,虽然当然可以玩一些游戏,制作一个WaitGroup并拥有一个定时器goroutine pop,但仅仅获得这个简单的功能似乎很乏味/烦人/效率低下(顺便说一下,我遇到的任何底层系统线程库都直接支持它)
编辑:是的,我们都读过http://www.golang-book.com/10/index.htm和https://blog.golang.org/pipelines-再次,创建更多的线程是一个“坏”(非性能)解决方案,和通道也不太适合这一点。想象一下一个典型的并发服务器Join()方法的用例。(请不要告诉我反转控件并使用一个API模式来代替。你并不总是有奢侈来改变你正在使用的API.)
6条答案
按热度按时间6yoyoihd1#
你可以实现一个条件变量,它只支持广播(无信号),有一个频道。https://gist.github.com/zviadm/c234426882bfc8acba88f3503edaaa36#file-cond2-go
你也可以在代码中使用这种替换通道并关闭旧通道的技术。Gist中的代码使用unsafe.Pointer和atomic操作来允许调用'Broadcast'而不获取主sync. Locker。然而在你自己的代码中,通常情况下,你应该从获取锁中广播,这样你就不需要做任何不安全/原子的事情。
当这个方法工作时,你可能还想 checkout :https://godoc.org/golang.org/x/sync/semaphore。如果你做了一个限制为1的加权信号量,那也会给你给予你需要的所有能力,这也是公平的。
r6vfmomb2#
不。没有简单的方法来做到这一点,并根据该线程,他们不会添加一个。(虽然也许与他们讨论它可能会让你在某处)
但总有一条艰难的路。两个选择:
1.运行您自己的具有此功能的
Cond
。(请参见https://golang.org/src/sync/cond.go)1.通过系统调用使用操作系统级别的功能。(可能是futex?)
这里的挑战--也是为什么它不是微不足道的原因--是goroutine不是线程。Go有它自己的自定义调度程序。创建自己的
Cond
将涉及到修补运行时的部分,而这些部分并不真正意味着要修补。(但是,就像我说的,这是可能的)如果这是限制的话,很抱歉。大多数go都很简单--你经常可以毫不费力地跳到下层。但是调度器不是这样的。它很神奇。
这个魔法适用于大多数东西,他们在
sync
中添加了一些东西来覆盖一些已知的情况。如果你觉得你找到了另一个,也许你可以说服他们添加它。(但这不仅仅是从另一种编程语言复制一个API,或者公开一个底层API的问题)daolsyd03#
从Go 1.21开始,有一种方法可以用新的
context.AfterFunc
来实现。甚至有这样的例子:字符串
2wnc66cl4#
我在今年的GopherCon演讲中概述了几种可能的替代方案(参见https://drive.google.com/file/d/1nPdvhB0PutEJzdCq5ms6UI58dp50fcAN/view)。“条件变量”部分从第37张幻灯片开始,但这种特定模式在备份幻灯片(101-105)中有更详细的介绍。
正如zviadm所指出的,一种选择(https://play.golang.org/p/tWVvXOs87HX)是关闭一个通道。
另一个选项(https://play.golang.org/p/uRwV_i0v13T)是让每个服务员分配一个1缓冲的频道,并让广播公司向缓冲区发送一个令牌进行广播。
如果该事件是一个持续的条件,如“队列为空”,第三个选项(https://play.golang.org/p/uvx8vFSQ2f0)是使用1缓冲通道,并让每个接收器重新填充缓冲区,只要条件持续。
w51jfk4q5#
https://gitlab.com/jonas.jasas/condchan允许等待超时。请看一个例子:
字符串
wswtfjt76#
我遇到了同样的问题,事实证明,使用一个通道很容易解决。
与任何条件变量一样,当您等待时,它需要持有互斥锁,并且强烈建议在您发出信号时持有它。
我写了一个遵循Cond协议的in实现,并添加了一个WaitOrbit。如果成功,它将返回true,如果超时,则返回false。
这是我的代码沿着一些测试用例!免责声明:这看起来工作正常,但还没有经过彻底的测试。而且,不保证公平性。等待的线程按照调度程序认为合适的顺序释放,不一定是先到先服务。
https://play.golang.org/p/K1veAOGbWZ
字符串