C# 按优先级排序的写入程序对共享资源的访问?
NET framework是否提供了一种实现对共享资源的访问的能力,以使一些试图访问该资源的编写器优先于其他编写器 我的问题有以下限制:C# 按优先级排序的写入程序对共享资源的访问?,c#,.net,multithreading,C#,.net,Multithreading,NET framework是否提供了一种实现对共享资源的访问的能力,以使一些试图访问该资源的编写器优先于其他编写器 我的问题有以下限制: 1.只能向资源授予1个并发写入请求 2.有许多写入程序正在等待访问此资源,但有些写入程序的优先级高于其他写入程序(缺少低优先级写入程序是可以的)。 3.线程关联不是必需的。一个线程可以设置锁,但另一个线程可以重置锁。 4.所有写入线程都来自同一进程 简言之,我需要一个原语来公开它的等待队列并允许修改访问它。如果没有这样的东西,那么有没有关于如何使用已经可用的类
1.只能向资源授予1个并发写入请求
2.有许多写入程序正在等待访问此资源,但有些写入程序的优先级高于其他写入程序(缺少低优先级写入程序是可以的)。
3.线程关联不是必需的。一个线程可以设置锁,但另一个线程可以重置锁。
4.所有写入线程都来自同一进程
简言之,我需要一个原语来公开它的等待队列并允许修改访问它。如果没有这样的东西,那么有没有关于如何使用已经可用的类(如Semaphore)为自己构建一个的提示?使用优先级队列来保存挂起的请求列表。请参见此处:。
按照kenny的建议,使用Stanard Monitor功能来锁定和通知要做什么和什么时候做。下面是一些我可以想出的快速脏代码。我会改进这一点,但作为一个POC,这是可行的
public class PrioritisedLock
{
private List<CountdownEvent> waitQueue; //wait queue for the shared resource
private Semaphore waitQueueSemaphore; //ensure safe access to wait queue itself
public PrioritisedLock()
{
waitQueue = new List<CountdownEvent>();
waitQueueSemaphore = new Semaphore(1, 1);
}
public bool WaitOne(int position = 0)
{
//CountdownEvent needs to have a initial count of 1
//otherwise it is created in signaled state
position++;
bool containsGrantedRequest = false; //flag to check if wait queue still contains object which owns the lock
CountdownEvent thisRequest = position<1 ? new CountdownEvent(1) : new CountdownEvent(position);
int leastPositionMagnitude=Int32.MaxValue;
waitQueueSemaphore.WaitOne();
//insert the request at the appropriate position
foreach (CountdownEvent cdEvent in waitQueue)
{
if (cdEvent.CurrentCount > position)
cdEvent.AddCount();
else if (cdEvent.CurrentCount == position)
thisRequest.AddCount();
if (cdEvent.CurrentCount == 0)
containsGrantedRequest = true;
}
waitQueue.Add(thisRequest);
foreach (CountdownEvent cdEvent in waitQueue)
if (cdEvent.CurrentCount < leastPositionMagnitude)
leastPositionMagnitude = cdEvent.CurrentCount;
//If nobody holds the lock, grant the lock to the current request
if (containsGrantedRequest==false && thisRequest.CurrentCount == leastPositionMagnitude)
thisRequest.Signal(leastPositionMagnitude);
waitQueueSemaphore.Release();
//now do the actual wait for this request; if it is already signaled, it ends immediately
thisRequest.Wait();
return true;
}
public int Release()
{
int waitingCount = 0, i = 0, positionLeastMagnitude=Int32.MaxValue;
int grantedIndex = -1;
waitQueueSemaphore.WaitOne();
foreach(CountdownEvent cdEvent in waitQueue)
{
if (cdEvent.CurrentCount <= 0)
{
grantedIndex = i;
break;
}
i++;
}
//remove the request which is already fulfilled
if (grantedIndex != -1)
waitQueue.RemoveAt(grantedIndex);
//find the wait count of the first element in the queue
foreach (CountdownEvent cdEvent in waitQueue)
if (cdEvent.CurrentCount < positionLeastMagnitude)
positionLeastMagnitude = cdEvent.CurrentCount;
//decrement the wait counter for each waiting object, such that the first object in the queue is now signaled
foreach (CountdownEvent cdEvent in waitQueue)
{
waitingCount++;
cdEvent.Signal(positionLeastMagnitude);
}
waitQueueSemaphore.Release();
return waitingCount;
}
}
公共类优先级锁定
{
private List waitQueue;//共享资源的等待队列
私有信号量waitQueueSemaphore;//确保安全访问等待队列本身
公共优先级锁()
{
waitQueue=新列表();
waitQueueSemaphore=新信号量(1,1);
}
公共bool WaitOne(内部位置=0)
{
//CountdownEvent的初始计数必须为1
//否则,它将在信号状态下创建
位置++;
bool containsGrantedRequest=false;//用于检查等待队列是否仍包含拥有锁的对象的标志
倒计时事件(此请求=位置)
cdEvent.AddCount();
else if(cdEvent.CurrentCount==位置)
thisRequest.AddCount();
如果(cdEvent.CurrentCount==0)
ContainesGrantedRequest=true;
}
waitQueue.Add(此请求);
foreach(waitQueue中的CountdownEvent cdEvent)
if(cdEvent.CurrentCount<最小位置幅值)
leastPositionMagnitude=cdEvent.CurrentCount;
//如果没有人持有锁,则将锁授予当前请求
if(containsGrantedRequest==false&&thisRequest.CurrentCount==leastPositionMagnitude)
此请求。信号(最小位置幅值);
waitQueueSemaphore.Release();
//现在实际等待这个请求;如果已经发出信号,它将立即结束
thisRequest.Wait();
返回true;
}
公共int Release()
{
int waitingCount=0,i=0,positionLeastMagnitude=Int32.MaxValue;
int grantedIndex=-1;
waitQueueSemaphore.WaitOne();
foreach(waitQueue中的CountdownEvent cdEvent)
{
如果(cdEvent.CurrentCount什么资源?某种类型的流?让写入程序尝试锁定,如果我不能将自己放入一个优先级队列中如何。当带锁的写入程序即将释放锁时,它可以检查队列并抓取下一个写入程序。@Will-该资源是一个COM dll,它不允许对任何方法或pro进行并发访问perty被它暴露了。它抛出一个“对象还没有准备好”异常,以防并发访问发生。@kenny-让我想想,如果我能利用你的想法,我明天会回复(这里已经很晚了)。你看过ReaderWriterLockSlim吗?那可以,我会试试。在.NET framework 4中,似乎还有一个名为System.Threading.CountdownEvent的新类,我可以用它创建我自己的机制。我将运行一些性能测试,看看是哪个实现(优先级队列+互斥体/监视器,还是我的类)资源密集度较低。我也希望您能就如何优化这一点发表意见。