我们有一些旧的应用程序通过基于目录的队列进行通信。队列中的每个项目都是一个文件,并且有一个头文件,用于维护队列中项目的文件名的有序列表。
当然,这个旧代码需要在推送和弹出项目时锁定队列。假设mkdir()是一个原子操作,它正在创建一个lock子目录 - 如果多个进程尝试创建一个目录,那么其中只有一个会成功。
我的一位同事一直试图追查一个不起眼的问题,他认为原因是这个锁定不再有效,当进程在不同的机器上运行时,以及当有问题的文件系统被挂载时在SAN上。
他有可能是正确的吗?
答案 0 :(得分:0)
我知道很老的问题,但我希望有人觉得这很有意思。
使用PowerShell创建共享文件夹以用作互斥锁时,我也得到了令人困惑的结果,所以我创建了一个测试脚本。
function New-FolderMutex {
try {
New-Item -ItemType directory -Path .\TheMutex -ErrorAction Stop > $null
$true
} catch {
$false
}
}
function Remove-FolderMutex {
Remove-Item -Path .\TheMutex
}
1..100 | % {
if (New-FolderMutex) {
Write-Host "Inside loop $_"
Remove-FolderMutex
}
}
当前目录位于网络共享中时,将运行此脚本。
当我在两个单独的PowerShell控制台中同时运行此脚本时,从错误消息中可以清楚地看出该方法注定失败了。调用Remove-Item会产生许多不同的错误,即使它只是由创建该文件夹的进程调用。在幕后似乎发生了一大堆非原子步骤。
当然,OP询问mkdir
(可能是系统调用),我的示例使用更高级别的PowerShell cmdlet,但我希望这有一些兴趣。
两个进程之一的输出示例(为简洁起见编辑)
Inside loop 30
Inside loop 31
Inside loop 32
Inside loop 33
Inside loop 34
Remove-Item : Access to the path 'H:\My Documents\PowerShell\MutexFolder\TheMutex' is denied.
At H:\My Documents\PowerShell\MutexFolder\Test-FolderMutex.ps1:93 char:5
+ Remove-Item -Path .\TheMutex
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (H:\My Documents...Folder\TheMutex:String) [Remove-Item], UnauthorizedAccessException
+ FullyQualifiedErrorId : RemoveItemUnauthorizedAccessError,Microsoft.PowerShell.Commands.RemoveItemCommand
Inside loop 39
Remove-Item : H:\My Documents\PowerShell\MutexFolder\TheMutex is a NTFS junction point. Use the Force parameter to delete or modify.
At H:\My Documents\PowerShell\MutexFolder\Test-FolderMutex.ps1:93 char:5
+ Remove-Item -Path .\TheMutex
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (H:\My Documents...Folder\TheMutex:DirectoryInfo) [Remove-Item], IOException
+ FullyQualifiedErrorId : DirectoryNotEmpty,Microsoft.PowerShell.Commands.RemoveItemCommand
Inside loop 42
Remove-Item : Could not find a part of the path 'H:\My Documents\PowerShell\MutexFolder\TheMutex'.
At H:\My Documents\PowerShell\MutexFolder\Test-FolderMutex.ps1:93 char:5
+ Remove-Item -Path .\TheMutex
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (H:\My Documents...Folder\TheMutex:String) [Remove-Item], DirectoryNotFoundException
+ FullyQualifiedErrorId : RemoveItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
Inside loop 44
Inside loop 45