暂停工作人员池

Suspend worker pool

使用 golang 实现的工作池看起来比

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

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

谢谢

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

在执行普通工作的 worker 中使用互斥锁的 Read 端,并要求在执行数据库同步操作时保持 Write 端。

至关重要的是,您必须确保 Read 在工作实际进行时举行。如果 worker 被阻塞等待更多工作,读锁必须 而不是 被持有,因为这将使挂起的 writers 饿死。


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

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

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()
}

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

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

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

  • Close all the worker ?

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

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

  • Use a chan in the worker to prevent getting a job if suspended ?

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

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