.net 是否存在全局命名读写器锁?

.net 是否存在全局命名读写器锁?,.net,locking,.net,Locking,我有多个asp.net web应用程序为一组文件提供服务。在提供文件之前,用户会定期更新文件,但如果文件正在使用,则无法更新 我可以通过使用命名互斥来解决这个问题,其中名称是文件路径(当然替换无效字符)。我在其他情况下也用过这个,但是你可以看到它的效率有多低。一次只能有一个进程提供文件 读写器锁是完美的,但它们设计为在单个进程中工作。另外,我必须为每个可能被更新的文件创建一个读写器锁,而且还有很多 我真正需要的是一个读写器锁,可以像互斥锁一样命名。有这样的事吗?或者可以使用现有的锁创建这样的东西

我有多个asp.net web应用程序为一组文件提供服务。在提供文件之前,用户会定期更新文件,但如果文件正在使用,则无法更新

我可以通过使用命名互斥来解决这个问题,其中名称是文件路径(当然替换无效字符)。我在其他情况下也用过这个,但是你可以看到它的效率有多低。一次只能有一个进程提供文件

读写器锁是完美的,但它们设计为在单个进程中工作。另外,我必须为每个可能被更新的文件创建一个读写器锁,而且还有很多


我真正需要的是一个读写器锁,可以像互斥锁一样命名。有这样的事吗?或者可以使用现有的锁创建这样的东西吗?

我认为没有任何东西可以满足您的要求(尽管我保留出错的权利)


您可以使用服务提供文件。这解决了两个问题。首先,正如您所说的,并发性问题。此外,即使您可以实现同步,但如果您开始进行负载平衡,它也会变得更加困难和丑陋。使用服务提供文件可能会降低性能,但可以解决同步问题。

可以使用互斥锁和信号量模拟读写器锁。如果我必须每秒访问它数千次,我不会这样做,但是如果每秒访问几十次或者几百次,它应该可以正常工作

此锁允许1个写入程序独占访问或N个(可能较大,但必须定义)读卡器并发访问

下面是它的工作原理。我将以10个阅读器为例

初始化一个命名互斥体(最初未标记)和一个带有10个插槽的命名信号量:

  Mutex m = new Mutex(false, "MyMutex");
  Semaphore s = new Semaphore(10, 10, "MySemaphore");
获取读卡器锁:

// Lock access to the semaphore.
m.WaitOne();
// Wait for a semaphore slot.
s.WaitOne();
// Release mutex so others can access the semaphore.
m.ReleaseMutex();
s.Release();
释放读卡器锁:

// Lock access to the semaphore.
m.WaitOne();
// Wait for a semaphore slot.
s.WaitOne();
// Release mutex so others can access the semaphore.
m.ReleaseMutex();
s.Release();
获取写入程序锁:

// Lock access to the seamphore
m.WaitOne();
// Here we're waiting for the semaphore to get full,
// meaning that there aren't any more readers accessing.
// The only way to get the count is to call Release.
// So we wait, then immediately release.
// Release returns the previous count.
// Since we know that access to the semaphore is locked
// (i.e. nobody can get a slot), we know that when count
// goes to 9 (one less than the total possible), all the readers
// are done.
s.WaitOne();
int count = s.Release();
while (count != 9)
{
    // sleep briefly so other processes get a chance.
    // You might want to tweak this value.  Sleep(1) might be okay.
    Thread.Sleep(10);
    s.WaitOne();
    count = s.Release();
}

// At this point, there are no more readers.
m.ReleaseMutex();
释放写入程序锁:

// Lock access to the seamphore
m.WaitOne();
// Here we're waiting for the semaphore to get full,
// meaning that there aren't any more readers accessing.
// The only way to get the count is to call Release.
// So we wait, then immediately release.
// Release returns the previous count.
// Since we know that access to the semaphore is locked
// (i.e. nobody can get a slot), we know that when count
// goes to 9 (one less than the total possible), all the readers
// are done.
s.WaitOne();
int count = s.Release();
while (count != 9)
{
    // sleep briefly so other processes get a chance.
    // You might want to tweak this value.  Sleep(1) might be okay.
    Thread.Sleep(10);
    s.WaitOne();
    count = s.Release();
}

// At this point, there are no more readers.
m.ReleaseMutex();

虽然很脆弱(每个使用这个的进程最好都有相同的信号量计数!),但我认为只要你不想太用力,它会做你想做的事情。

这个怎么样?不要提供文件。提供文件的副本。当您需要进行更改时,创建一个新文件,并从那时起提供该文件的副本。

我很感激,但我看到了通过避免Thread.Sleep()和避免多个读卡器试图同时获取时的锁争用来提高性能的机会

初始化 读取器 作家
简单地尝试打开文件本身,然后捕获适当的异常以检查它是否已被锁定,这有什么不对吗?如果需要的话,反复投票应该不是问题。这似乎是迄今为止最简单的解决方案。是否可以转移到数据库解决方案而不是使用文件?我之所以提出这个建议,是因为听起来你真正想要的是交易。你读过这个问题吗,还是仅仅是标题?他表示要避免互斥。不够好。:)修好了,我不太明白。如果你在其中一个应用程序中创建互斥和信号量,那么其他应用程序如何访问互斥和信号量?@Trevor:因为它们是操作系统对象。基于访问权限,命名对象是全局可访问的。看见基本上,命名的Windows对象可以跨进程全局访问。@JimMischel:释放writer互斥锁的建议时间跨度是多少?@IvoryCoder:一般的想法是,您可以在尽可能短的时间内保持任何锁。在这里的writer锁的情况下尤其如此,因为这是一个排他锁:如果您持有写锁,则没有其他线程或进程可以获得读或写锁。因此,获取writer锁,写入需要写入的数据,然后释放。建议的时间跨度是:“只要您需要,但不再需要。”