如何使用互斥锁
本文关键字:何使用 | 更新日期: 2023-09-27 18:11:46
我有一个线程,这是发送数据存储在类型为List<的缓冲区;字符串>通过tcp。另一个线程正在写入缓冲区。由于我不太熟悉c#,我想知道我应该如何正确使用锁或互斥锁。
这是我最终想要使用的代码:
while(buffer.isLocked())
{
buffer.wait();
}
buffer.lockBuffer();
buffer.add(tcpPacket);
buffer.unlockBuffer();
buffer.notify();
这是我当前的代码。我希望有人能帮我完成它。
public class Buffer
{
private Mutex mutex;
private List<string> buffer;
private bool locked = false;
public Buffer()
{
mutex = new Mutex(false);
buffer = new List<string>();
}
public bool isLocked()
{
return locked;
}
public void lockBuffer()
{
if (!locked)
{
//...
locked = true;
}
}
public void unlockBuffer()
{
if(locked)
{
mutex.ReleaseMutex();
locked = false;
}
}
public void wait()
{
mutex.WaitOne();
}
public void notify()
{
//...
}
}
最好使用System.Collections.Concurrent.BlockingCollection
。它不需要外部同步。
对于那些不使用4.0的
using System;
using System.Collections.Generic;
using System.Threading;
namespace MyCollections
{
public class BlockingQueue<T> : IDisposable
{
Queue<T> _Queue = new Queue<T>();
SemaphoreSlim _ItemsInQueue = null;
SemaphoreSlim _FreeSlots = null;
int _MaxItems = -1;
public BlockingQueue(int maxItems=Int32.MaxValue)
{
_MaxItems = maxItems;
_ItemsInQueue = new SemaphoreSlim(0, maxItems);
_FreeSlots = new SemaphoreSlim(maxItems, maxItems);
}
public void Dispose()
{
if (_ItemsInQueue != null) _ItemsInQueue.Dispose();
if (_FreeSlots != null) _FreeSlots.Dispose();
}
public int Count
{
get { return _ItemsInQueue.CurrentCount; }
}
public void Add(T item)
{
if(_MaxItems != Int32.MaxValue) _FreeSlots.Wait();
lock (this)
{
_Queue.Enqueue(item);
_ItemsInQueue.Release();
}
}
public T Take()
{
T item = default(T);
_ItemsInQueue.Wait();
lock (this)
{
item = _Queue.Dequeue();
if (_MaxItems != Int32.MaxValue) _FreeSlots.Release();
}
return item;
}
}
}
下面的代码不是线程安全的。如果两个线程同时进入这个方法,它们可能都成功通过If条件。
public void lockBuffer()
{
if (!locked)
{
//...
locked = true;
}
}
你可能只是想做这样的事情:
lock (_sycnObject)
{
buffer.lockBuffer();
buffer.add(tcpPacket);
buffer.unlockBuffer();
buffer.notify();
}
我不认为你在做一些复杂的事情,需要更多的简单使用锁语句。
我不会使用互斥锁,因为我认为您没有处理多进程同步。锁非常好,而且更容易实现:
class Buffer
{
private readonly object syncObject = new object();
private readonly List<string> buffer = new List<string>();
public void AddPacket(string packet)
{
lock (syncObject)
{
buffer.Add(packet);
}
}
public void Notify()
{
// Do something, if needed lock again here
// lock (syncObject)
// {
// Notify Implementation
// }
}
}
用法显然是(如您所要求的):
var myBuffer = new Buffer();
myBuffer.Add("Hello, World!");
myBuffer.Notify();