关于本文
本文是通过利用生成式 AI 的自动化生成流程创建的。我们确认了 Linux 的 flock 以及 .NET 的 Named Mutex 的第一手资料,并从相同的角度对比了 Linux 和 Windows 如何防止“同一项定期处理启动两次”的情况。验证状态:🧪 Linux flock 执行已验证,Windows Mutex 官方规范已确认
信息确认基准日:2026年10月5日
在使用 cron、systemd timer、Windows 任务计划程序等定期处理时,下一次执行有时会在上一次处理结束之前开始。对于备份、文件更新和博客发布等处理,重复启动会导致重复处理和冲突。
防止此类事故的基础是排他锁。
在 Linux 中尝试运行两次 flock
在终端 1 中执行。
flock -n /tmp/papanda-demo.lock bash -c 'echo "LOCK取得"; sleep 10; echo "LOCK解除"'
在 10 秒内在终端 2 中执行相同的命令。-n 是指如果无法获取锁则不等待直接退出的选项。
在此环境中重叠运行两个进程,并确认了第二个进程无法获取锁。
flowchart TD
A["処理A 起動"] --> B{"flock取得?"}
B -- Yes --> C["処理Aを実行"]
D["処理B 起動"] --> E{"同じflock取得?"}
E -- No --> F["二重実行せず終了"]
C --> G["処理終了・lock解放"]
仅凭 lock 文件的存在无法断定状态
/tmp/papanda-demo.lock 看到这样的文件名时,文件本身似乎拥有锁的状态。
util-linux 的 flock 处理对文件、目录或打开的文件描述符的锁。因此,文件存在与当前是否持有锁是两码事。
在生产环境中,不要凭“有lock文件残留所以删掉就行”来下结论,而应先检查所有者进程和服务的状态。
如果等待,请设定超时时间
与其立即失败,不如等待一段时间。
flock -w 10 /tmp/papanda-demo.lock bash -c 'echo "処理開始"; sleep 20; echo "処理終了"'
在定时任务中,当无法获取锁时,需要确定是选择“立即放弃”、“等待几秒”还是“通知监控”。
在Windows上可以使用Named Mutex
.NET的 System.Threading.Mutex 是一种也可用于进程间同步的排他控制方式。
$mutex = [System.Threading.Mutex]::new(
$false,
"Local\PapandaLockDemo"
)
$locked = $mutex.WaitOne(0)
if ($locked) {
try {
Write-Host "[SUCCESS] LOCK取得"
Start-Sleep -Seconds 5
}
finally {
$mutex.ReleaseMutex()
$mutex.Dispose()
}
}
else {
Write-Host "[BLOCKED] 別プロセスが実行中"
$mutex.Dispose()
}
如果打开两个PowerShell,并在第一个等待5秒的过程中运行第二个,就可以通过是否能获取同名Mutex来判断是否重复启动。
这部分Windows相关内容尚未在实机上确认,因此不作为实际测量结果处理。
Local和Global并不相同
本教程将使用 Local\PapandaLockDemo。
在跨会话等用途中会涉及 Global\,但权限和运行条件也会随之改变。请先确定“想要在哪些进程之间进行排他控制”。
还需考虑异常终止的Mutex
在.NET中,如果持有Mutex的线程未释放(Release)就结束了,下一次获取时可能会引发 AbandonedMutexException。
这表明上一次处理可能中途退出了。设计时需要确认受保护的文件或数据是否处于不完整状态。
多个锁同时使用时也可能发生死锁
処理A: LOCK-1取得 → LOCK-2待ち 処理B: LOCK-2取得 → LOCK-1待ち
flowchart LR
A["処理A<br>LOCK-1保持"] --> B["LOCK-2待ち"]
C["処理B<br>LOCK-2保持"] --> D["LOCK-1待ち"]
B --> C
D --> A
对策的基本原则是:统一获取顺序、缩短保持时间、设置超时以及不增加不必要的锁。
在定时处理中,将锁的获取与主处理的成败分离开来
如果是备份,
起動 ↓ ロック取得 ↓ 取得できなければ「前回処理中」として終了 ↓ バックアップ実行 ↓ 結果確認 ↓ ロック解放
即是如此。
获取到锁并不意味着备份成功。主处理的成功与失败需要单独记录。
Linux与Windows的共同点
| Linux flock | Windows 命名互斥体 |
|---|---|
| 能够排他并发执行 | 能够排他并发执行 |
| 利用 file/FD | 操作系统的命名同步对象 |
-n / -w控制等待方式 | WaitOne(timeout)控制等待方式 |
| 切勿仅凭锁文件名断定状态 | 仅获取互斥体并不能保证受保护数据的完整性 |
尽管实现方法不同,设计上面临的问题是相同的。明确与谁竞争、获取不到时是等待还是放弃、异常终止后需要检查什么。
