Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 等待前释放锁,等待后重新获取_C#_Java_Multithreading_Locking - Fatal编程技术网

C# 等待前释放锁,等待后重新获取

C# 等待前释放锁,等待后重新获取,c#,java,multithreading,locking,C#,Java,Multithreading,Locking,在Java中,可以将多个条件对象关联到单个可重入锁。C的等价物是什么? 真实世界示例:中的示例实现使用两个绑定到同一锁的条件对象notFull和notEmpty。这个例子怎么能翻译成C# 背景:我经常发现Java代码使用两个条件对象来表示不同的状态,与同一个锁关联;在C#中,似乎你可以 调用Monitor。在对象上输入,然后输入Monitor.WaitOne/Monitor.Pulse,但这只是一个条件 使用多个Auto/ManualResetEvent对象,但这些对象在等待后无法自动重新获取

在Java中,可以将多个
条件
对象关联到单个
可重入锁
。C的等价物是什么?

真实世界示例:中的示例实现使用两个绑定到同一锁的
条件
对象
notFull
notEmpty
。这个例子怎么能翻译成C#

背景:我经常发现Java代码使用两个
条件
对象来表示不同的状态,与同一个
锁关联;在C#中,似乎你可以

  • 调用
    Monitor。在对象上输入
    ,然后输入
    Monitor.WaitOne
    /
    Monitor.Pulse
    ,但这只是一个条件
  • 使用多个
    Auto/ManualResetEvent
    对象,但这些对象在等待后无法自动重新获取给定的锁

注意:我能想到一种方法:在单个对象上使用
Monitor.WaitOne
/
Monitor.pulsell
,并在醒来后检查情况;这也是在Java中防止虚假唤醒所做的。但是,它实际上不起作用,因为它强制您调用
pulsell
而不是
Pulse
,因为
Pulse
可能会唤醒等待其他条件的线程。不幸的是,使用
pulsell
而不是
Pulse
会对性能产生影响(线程竞争相同的锁)。

我认为如果您正在进行新的开发,并且可以使用.NET 4或更高版本,那么新的并发集合类将更好地为您服务,例如

但是如果你不能采取行动,并且严格地回答你的问题,在.NET中,这有点简化了imho,要实现一个prod/cons模式,你只需等待,然后像下面那样脉冲(注意,我在记事本上键入了这个)

//队列中最多有1000个项目
私有整数_计数=1000;
专用队列_myQueue=新队列();
私有静态对象_door=新对象();
public void AddItem(字符串someItem)
{
锁(门)
{
而(\u myQueue.Count==\u Count)
{
//已达到最大项目,让我们等待,直到有空间
监视器,等等(门);
}
_myQueue.Enqueue(someItem);
//发出信号,以便唤醒等待插入项目的广告
//一次一个,这样他们就不会试图把不在那里的项目排出来
监视器脉冲(门);
}
}
公共字符串removietem()
{
字符串项=null;
锁(门)
{
而(_myQueue.Count==0)
{
//队列中没有项目,请等待“直到有项目”
监视器,等等(门);
}
item=_myQueue.Dequeue();
//我们有东西拿出来了
//因此,如果有线程等待,将一次唤醒一个线程,这样我们就不会使队列中的线程过多
监视器脉冲(门);
}
退货项目;
}

更新:为了消除任何混淆,请注意释放锁,因此不会出现死锁

我认为如果您正在进行新的开发,并且可以使用.NET 4或更高版本,那么新的并发集合类会更好地为您服务,如

但是如果你不能采取行动,并且严格地回答你的问题,在.NET中,这有点简化了imho,要实现一个prod/cons模式,你只需等待,然后像下面那样脉冲(注意,我在记事本上键入了这个)

//队列中最多有1000个项目
私有整数_计数=1000;
专用队列_myQueue=新队列();
私有静态对象_door=新对象();
public void AddItem(字符串someItem)
{
锁(门)
{
而(\u myQueue.Count==\u Count)
{
//已达到最大项目,让我们等待,直到有空间
监视器,等等(门);
}
_myQueue.Enqueue(someItem);
//发出信号,以便唤醒等待插入项目的广告
//一次一个,这样他们就不会试图把不在那里的项目排出来
监视器脉冲(门);
}
}
公共字符串removietem()
{
字符串项=null;
锁(门)
{
而(_myQueue.Count==0)
{
//队列中没有项目,请等待“直到有项目”
监视器,等等(门);
}
item=_myQueue.Dequeue();
//我们有东西拿出来了
//因此,如果有线程等待,将一次唤醒一个线程,这样我们就不会使队列中的线程过多
监视器脉冲(门);
}
退货项目;
}

更新:若要清除任何混淆,请注意释放锁,因此不会出现死锁

@Jason如果队列已满,而您只唤醒一个线程,则不能保证该线程是使用者。它可能是一个生产者,而你被卡住了。

@Jason如果队列已满,而你只唤醒了一个线程,你就不能保证该线程是消费者。它可能是一个生产者,你会被卡住。

我没有遇到太多希望在锁中共享状态的C代码。您可以使用
SemaphoreSlim
(但我建议
ConcurrentQueue(T)
BlockingCollection(T)

公共类BoundedBuffer
{
私有只读信号量lim _locker=新信号量lim(1,1);
私有只读int_maxCount=1000;
专用只读队列_项;
公共整数计数{get{return\u items.Count;}}
公共边界缓冲区()
{
_项目=新队列(_maxCount);
}
公共边界缓冲区(整数最大计数)
{
_maxCount=maxCount;
_项目=新队列(_maxCount);
}
公共作废认沽权(T项,取消代币)
{
_储物柜。等待(令牌);
尝试
{
而(\u maxCount==\u items.Count)
{
_锁定器释放();
Thread.SpinWait(1000);
_储物柜。等待(令牌);
// max is 1000 items in queue
private int _count = 1000;

private Queue<string> _myQueue = new Queue<string>();

private static object _door = new object();

public void AddItem(string someItem)
{
    lock (_door)
    {
        while (_myQueue.Count == _count)
        {
            // reached max item, let's wait 'till there is room
            Monitor.Wait(_door);
        }

        _myQueue.Enqueue(someItem);
        // signal so if there are therads waiting for items to be inserted are waken up
        // one at a time, so they don't try to dequeue items that are not there
        Monitor.Pulse(_door);
    }
}

public string RemoveItem()
{
    string item = null;

    lock (_door)
    {
        while (_myQueue.Count == 0)
        {
            // no items in queue, wait 'till there are items
            Monitor.Wait(_door);
        }

        item = _myQueue.Dequeue();
        // signal we've taken something out
        // so if there are threads waiting, will be waken up one at a time so we don't overfill our queue
        Monitor.Pulse(_door);
    }

    return item;
}
public class BoundedBuffer<T>
{
    private readonly SemaphoreSlim _locker = new SemaphoreSlim(1,1);
    private readonly int _maxCount = 1000;
    private readonly Queue<T> _items;

    public int Count { get { return _items.Count; } }

    public BoundedBuffer()
    {
        _items = new Queue<T>(_maxCount);
    }

    public BoundedBuffer(int maxCount)
    {
        _maxCount = maxCount;
        _items = new Queue<T>(_maxCount);
    }

    public void Put(T item, CancellationToken token)
    {
        _locker.Wait(token);

        try
        {
            while(_maxCount == _items.Count)
            {
                _locker.Release();
                Thread.SpinWait(1000);
                _locker.Wait(token);
            }

            _items.Enqueue(item);
        }
        catch(OperationCanceledException)
        {
            try
            {
                _locker.Release();
            }
            catch(SemaphoreFullException) { }

            throw;
        }
        finally
        {
            if(!token.IsCancellationRequested)
            {
                _locker.Release();
            }
        }
    }

    public T Take(CancellationToken token)
    {
        _locker.Wait(token);

        try
        {
            while(0 == _items.Count)
            {
                _locker.Release();
                Thread.SpinWait(1000);
                _locker.Wait(token);
            }

            return _items.Dequeue();
        }
        catch(OperationCanceledException)
        {
            try
            {
                _locker.Release();
            }
            catch(SemaphoreFullException) { }

            throw;
        }
        finally
        {
            if(!token.IsCancellationRequested)
            {
                _locker.Release();
            }
        }
    }
}