0

使用看起来比这更接近的工作池的 golang 实现

我想暂停我的工作人员几秒钟,同时像事务处理一样进行数据库同步。我不希望我的同步数据被另一个潜在的不受控制的工作人员更新。

暂停工作的最佳方法是什么?

  • 关闭所有工人?
  • 如果被暂停,请在工人中使用 chan 以防止获得工作?
  • 在处理工作之前使用全局标志在每个工作人员中设置锁定?

谢谢

4

1 回答 1

4

如果要实现数据库同步或至少向二进制文件发送信号,则可以RWMutex为此目的滥用 an。

在 worker 中做普通工作时使用Readmutex 的边,并要求在 Write执行数据库同步操作时保持边。

至关重要的是,您必须确保Read仅在工作实际发生时才举行。如果工作人员被阻塞等待更多工作,则不得持有读锁,因为这会使挂起的写入者饿死。


如果您使用它,我强烈建议您在代码中添加有关互斥锁的预期行为的文档,因为这在读取和写入操作方面有些不标准。

如果您想要一个更通用的解决方案,您还可以包装它并从派生接口导出不同的方法,使用更好的名称,如示例所示:

type WorkerGroupLocker struct {
    sync.RWMutex
}

func (lock *WorkerGroupLocker) LockWorker() {
    lock.RLock()
}

func (lock *WorkerGroupLocker) UnlockWorker() {
    lock.RUnlock()
}

func (lock *WorkerGroupLocker) LockBackgroundSync() {
    lock.Lock()
}

func (lock *WorkerGroupLocker) UnlockBackgroundSync() {
    lock.Unlock()
}

任何解决方案都必须解决这些一般问题:

  • 要求所有工人停止工作。
  • 确保在允许开始数据库工作之前所有工作人员都已停顿。
  • 向工人发出可以安全继续工作的信号。

这样做的替代方法包括以下内容,但在我看来,以下所有内容都将比使用互斥锁复杂得多(因此容易出现错误):

  • 关闭所有工人?

    在数据库工作开始之前要求工作人员停止工作将实现所需的互斥。您需要一种向它们发出停止信号的方法,以及一种检测何时确实完成的机制。

    无论如何,有人可能会争辩说您无论如何都需要这样做,以确保您在程序终止时干净地关闭。但是,程序终止是致命的,因此您不需要像此数据库同步工作所需的那样干净地启动和停止池。

  • 如果被暂停,请在工人中使用 chan 以防止获得工作?

    这实施起来会很复杂,因为您需要向所有工作人员发出停止工作的信号,并确保他们在开始工作之前确实停止了积极处理工作。反过来也需要:重新开始的信号。

涉及最少代码的工作的最简单工具是互斥锁。我建议使用它。

于 2018-09-05T21:47:53.980 回答