c# - 多个线程访问一个返回方法,带锁是线程安全的吗?

标签 c# multithreading thread-safety

我正在尝试从多个线程访问一个方法,我不确定这是否是线程安全的。如果不是,确保安全的最有效方法是什么?

我考虑了每个人的见解,我的最终产品如下所示,我还选择对数据包本身进行回收。

我的数据包池类

using System.Collections.Generic;

namespace Networking
{
    public class PacketPool
    {
        private Queue<Packet> pool = new Queue<Packet>();
        private readonly object instance = new object();

        public Packet CreatePacket(string method)
        {
            lock (instance)
                return pool.Count == 0 ? new Packet() { Pool = this } : 
                       pool.Dequeue();
        }

        public void Recycle(Packet packet)
        {
            lock(instance)
               pool.Enqueue(packet);
        }
    }
}

数据包类

using System;
using System.Net;

namespace Networking
{
    public class Packet 
    {
        public Protocol Proto = Protocol.Sequenced;
        public PacketFlags Flag = PacketFlags.None;
        public Fragment Fragmented = Fragment.NotFragged;
        public SendType SendType = SendType.Raw;
        public EndPoint RemoteEp = new IPEndPoint(IPAddress.Any, 0);
        public byte[] Buffer = new byte[512];
        public int Count = 0;
        public int Ptr = 8;
        public int Bits { get; set; } = 0;
        public ushort Id = 0;
        public ushort Lead = 0;
        public PacketPool Pool;

        public void Recycle()
        {
            Bits = 0;

            if (Buffer.Length > 512)
                Array.Resize(ref Buffer, 512);

            Count = 0;
            Flag = PacketFlags.None;
            Fragmented = Fragment.NotFragged;
            Proto = Protocol.Sequenced;
            Ptr = 8;
            Lead = 0;
            SendType = SendType.Raw;
            Pool.Recycle(this);
        }
    }
}

希望上述解决方案能让生活更轻松。

最佳答案

只要数据包本身不在单独的线程上修改,您显示的代码看起来就是线程安全的。您还可以考虑使 PacketPool 类成为线程安全的,以节省一些宝贵的锁定时间。

您可以通过将 Queue 替换为 ConcurrentQueue 来简化它.

请注意,您正在修改发送到Recycle方法中的数据包。我建议使数据对象不可变,以避免意外行为。

public class PacketPool
{
    public ConcurrentQueue<Packet> pool = new ConcurrentQueue<Packet>(2000);

    public Packet CreatePacket(string method)
    {
        if (pool.TryDequeue(out Packet packet))
        {
            return packet;
        }

        return new Packet();
    }

    public void Recycle(Packet packet)
    {
        packet.Bits = 0;

        if (packet.Buffer.Length > 512)
            Array.Resize(ref packet.Buffer, 512);

        packet.Count = 0;
        packet.Flag = PacketFlags.None;
        packet.Fragmented = Fragment.NotFragged;
        packet.Proto = Protocol.Sequenced;
        packet.Ptr = 8;
        packet.Lead = 0;
        packet.SendType = SendType.Raw;
        pool.Enqueue(packet);
    }
}

关于c# - 多个线程访问一个返回方法,带锁是线程安全的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56779841/

相关文章:

java - 2D volatile 数组 : will self-assignment help or do I need AtomicIntegerArray?

c# - 使用自定义逻辑的 Entity Framework 数据迁移?

c++ - 什么操作称为互锁?

ios - +(void) 初始化线程安全

c# - 对 IIS 的单个 Web 请求是否停留在单个线程上?

c++ - pthread_cond_wait() 之前的检查标志

c# - 在 WPF 中使用 MVVM 打开新窗口的推荐方法是什么

c# - 在 Visual Studio 2013 中为 .NET 3.5 调试添加调试符号

c# - 为 Sentinel 配置配置 ASP.NET Redis session 状态提供程序

multithreading - 将 SharpArchitecture 的 NHibernateSession 与不同的线程结合使用