Golang中的信号量通过以下渠道实现:
一个例子是:
https://sites.google.com/site/gopatterns/concurrency/semaphores
语境:
我们有几百台服务器,并且我们希望限制访问的共享资源.因此,对于给定的资源,我们希望使用信号量来限制对这些服务器的仅5个并发访问的访问.为此,我们计划使用锁服务器.当机器访问资源时,它将首先向锁定服务器注册它正在通过密钥访问资源.然后当它完成时,它会向锁定服务器发送另一个请求,说它已完成并释放信号量.这可确保我们将对这些资源的访问限制为最大数量的并发访问.
问题:如果出现问题,想要优雅地处理这个问题.
题:
你如何在信号量上实现超时?
例:
假设我的信号量大小为5.同时有10个进程试图获取信号量中的锁,因此在这种情况下只有5个将获取它.
有时候,进程会在没有响应的情况下死掉(真正的原因有点难以解释,但基本上有时候进程可能无法解锁它)因此导致问题,因为信号量中的空间现在被永久锁定.
所以我想暂停一下.以下是一些问题:
这些过程将在2秒到60分钟之间的任何时间运行.
我们有一些竞争条件,因为如果它超时然后进程试图解锁它,那么我们已经解锁了两次信号量而不是一次.反之亦然,我们首先解锁它然后超时.
如何获取上面发布的建议模式并将其转换为具有超时的线程安全信号量?
最佳答案 要弄清楚你想要完成什么有点困难,但从我所知道的,你正试图让并发的goroutine访问共享资源,如果事情进展不顺利,可以优雅地处理它.关于如何处理这个问题,我有几点建议.
1)使用同步包中的WaitGroup:http://golang.org/pkg/sync/#example_WaitGroup
使用此策略,您基本上在每次调用新goroutine之前添加到计数器并使用延迟来确保它从计数器中删除(因此,无论是超时还是由于其他原因返回,它仍将从计数器中删除).然后使用wg.Wait()命令确保在返回所有go例程之前它不再继续.这是一个例子:http://play.golang.org/p/wnm24TcBZg请注意,如果没有wg.Wait(),它将不会等待go例程完成,然后从main返回并终止.
2)使用time.Ticker自动超时:http://golang.org/pkg/time/#Ticker
这种方法基本上会设置一个定时器,它将以设定的间隔触发.您可以使用此计时器来控制基于时间的事件.基本上这必须在for循环中运行,等待通道被输入一个tick,如下例所示:http://play.golang.org/p/IHeqmiFBSS
同样,不完全确定你想要完成什么,但是你可以考虑将这两种方法结合起来,这样如果你的进程超时并且处于一个循环中,则自动收报机将捕获它并在一段时间后返回并调用延迟wg.Done()函数使得等待它的代码部分继续运行.希望这至少有点帮助.