使用 scanningMutex 锁来保证在进行扫描时只能运行一个任务。
下面是具体的机制:
锁的作用:通过 scanningMutex 锁确保在扫描任务运行期间,其他任务无法开始。这种方式避免了多个扫描任务并发执行可能导致的问题。
isScanning 标志:isScanning 是一个布尔值标志,用于表示扫描是否正在进行中。初始值为 false,当开始扫描时将其设置为 true,扫描结束后再设置为 false。
获取锁:在 AssetScanningCreateEndpoint 方法中,首先获取 scanningMutex 锁来检查 isScanning 标志。如果 isScanning 为 true,说明扫描正在进行中,方法会返回一个错误提示,告知用户当前扫描任务正在进行。
释放锁:如果没有正在进行的扫描任务,则释放锁并将 isScanning 设置为 true,然后启动一个新的 goroutine 进行扫描任务。
启动 goroutine:在 goroutine 中,重新获取 scanningMutex 锁,执行扫描任务后,确保将 isScanning 标志设置回 false,并释放锁。这确保了即使在扫描任务执行过程中发生错误,锁也会被正确释放,从而允许后续任务的启动。
锁的使用说明:
锁定检查:在主方法中,使用 scanningMutex.Lock() 和 scanningMutex.Unlock() 来保护对 isScanning 标志的访问。这确保了在检查和修改 isScanning 标志时不会出现并发问题。
并发安全:通过使用 defer 在 goroutine 中确保 scanningMutex 锁的释放,即使扫描任务发生错误,锁也会被释放,确保系统的并发安全。
func (api AssetScanningApi) AssetScanningCreateEndpoint(c echo.Context) error {
portType := c.QueryParam("portType")
ip := c.QueryParam("ip")
atoi, err := strconv.Atoi(portType)
if err != nil {
return err
}
scanningMutex.Lock()
if isScanning {
scanningMutex.Unlock()
return errors.New("scan in progress, please wait")
}
isScanning = true
scanningMutex.Unlock()
go func() {
defer func() {
scanningMutex.Lock()
isScanning = false
scanningMutex.Unlock()
}()
// 调用 SendassetScanning 方法
err := service.AssetScanningService.SendassetScanning(ip, atoi)
if err != nil {
log.Error("Scan failed: ", err)
return
}
}()
return Success(c, "扫描任务已提交")
}