如何使用互斥锁

发布于 2024-12-11 11:20:30 字数 1037 浏览 0 评论 0原文

我有一个线程,正在发送存储在 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()
    {
        //...
    }
}

I have one thread, that is sending data stored in a buffer of type List< string> via tcp. Another thread is writing into the buffer. As I am not very familiar with c# I'd like to know how I should use lock or Mutex correctly.

This is the code I'd like to use eventually:

 while(buffer.isLocked()) 
 { 
    buffer.wait();
 }

  buffer.lockBuffer();
  buffer.add(tcpPacket);
  buffer.unlockBuffer();
  buffer.notify();

This is my current code. I hope someone can help me complete it.

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()
    {
        //...
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

潜移默化 2024-12-18 11:20:30

如果您使用 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;
        }
    }
}

It would be better if you use System.Collections.Concurrent.BlockingCollection. It doesn't require an external sync.

For those who don't use 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;
        }
    }
}
嗫嚅 2024-12-18 11:20:30

以下代码不是线程安全的。如果两个线程同时进入此方法,则两个线程都可能成功通过 if 条件。

public void lockBuffer()
{
    if (!locked)
    {
        //...
       locked = true; 
    }
}

您可能只是想做这样的事情:

lock (_sycnObject)
{
  buffer.lockBuffer();
  buffer.add(tcpPacket);
  buffer.unlockBuffer();
  buffer.notify();
}

我不认为您正在做一些复杂的事情,需要的不仅仅是简单易用的锁定语句。

The following code is not thread-safe. If two threads are entering this method at the same time, both might pass the if condition successfully.

public void lockBuffer()
{
    if (!locked)
    {
        //...
       locked = true; 
    }
}

You simply might want to do something like this:

lock (_sycnObject)
{
  buffer.lockBuffer();
  buffer.add(tcpPacket);
  buffer.unlockBuffer();
  buffer.notify();
}

I don't think you're doing something sophisticated that requires more than the simple to use lock-statement.

两仪 2024-12-18 11:20:30

我不会使用互斥体,因为我想您不处理多进程同步。锁非常好并且更容易实现:

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();

I wouldn't use Mutexes since I suppose you aren't dealing with multiple processes synchronization. Locks are pretty fine and simpler to implement:

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
        // }
    }
}

The usage is obviously (as you requested):

var myBuffer = new Buffer();
myBuffer.Add("Hello, World!");
myBuffer.Notify();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文