zoukankan      html  css  js  c++  java
  • 并发,非等分,环形缓冲区的一些疑问。。。

    最近手里的程序需要用到这么个东西

    乍一看,好像很简单。但是实际操作起来感觉好复杂。

    总结下来主要集中在以下几个方面:

    1.分配(写入)的时候是顺序写入的,但是多线程状况下,每次写入完成时间是不确定的。这样一来似乎每个块分配出去的缓冲区都要进行跟踪。而跟踪的难点也就在于,写入完成时间完全是随机的。

    那么当我程序 需要访问并读取这个缓冲区的数据时,如何判断哪些连续部分已经写完。。。?

    要维护一个自动排序的列表,并且要二分查找。并且还要区分缓冲区会写(就是回到头上写入的情况),并且还要记录缓冲区尾部的位置(以供读取程序进行读取)。

    这样一来问题似乎变得十分复杂化了。。。。十分非常复杂。而且每次分配内存的时候 都要考虑上面所有情况。。。真是很复杂。

    2.好的,还有一个严重的问题就是,当环形缓冲区溢出的时候 应该如何处理。这是一个让人非常头疼的问题。

    应该说判断是否 满,不难。但是要判断,如何处理问题来了。既然是缓冲区 当然是放数据喽。。。所以不可能放弃数据吧...?

    那么我唯一想到的解决方案就是再开辟一个临时内存空间,保存这块来不及处理的数据。但是,这似乎又失去了环形缓冲的优势。。。

    真尼玛太纠结了。。。所以,最好还是要适当地分配比使用率大一些的缓冲区。。。?啥?不懂?我也不懂。好吧其实,我的应用的场合又比较特殊。

    是网络层面的,由于发送速度不可能是恒定的,接受的数据量也无法准确预测,因此不可能确定缓冲区的准确大小。。。

    好吧,。。。⊙﹏⊙b汗

    我太纠结了。这个问题困扰了,很久很久了。。。。如果有大神看到的话,不妨指点指点。

     下面是一小段半吊子。。。。(智商捉急唉,写到一点点心力交瘁了,写不下去了)

        public class ShareBuffer
        {
            public ShareBuffer(int size)
            {
                buffer = new byte[size];
            }
    
            public byte[] buffer;
    
    
    
            public int CurOffSet;
            public int LastSendOffSet;
            //public SortedDictionary<int, ArraySegment<byte>> RecevieingOffList = new SortedDictionary<int, ArraySegment<byte>>();
            //public SortedDictionary<int, ArraySegment<byte>> ProRecevieingOffList = new SortedDictionary<int, ArraySegment<byte>>();
            //public SortedSet<int> RecevieingOffSets = new SortedSet<int>(); 
    
            public ArraySegment<byte> Take(int length)
            {
                int AddCur = CurOffSet;
                if (AddCur < buffer.Length)//如果已经被其他线程改得超出了Length,那么本线程就不参与了
                {
                    AddCur = Interlocked.Add(ref CurOffSet, length);//拿到Offset+Count这块缓冲区的范围
                    if (AddCur < buffer.Length)//再次判断范围是否超过缓冲区大小
                    {
                        goto Do;
                        //
                    }
                }
                Start:
                //如果超过,从缓冲区的开头处从头再来
                AddCur = Interlocked.CompareExchange(ref CurOffSet, 0, AddCur);//如果其他线程 没有更新这个值为0,那就当前线程来做这件事
                //AddCur = Interlocked.Exchange(ref CurOffSet, 0);
                AddCur = Interlocked.Add(ref CurOffSet, length);//直接分配内存,不需要关注CurOffSet的值
    
                if(AddCur > buffer.Length)
                {
                    goto Start;
                }
    
    
                Do:
                //上面是分配内存
                int AddrOffsetStart = AddCur - length;
    
                //int first = RecevieingOffList.Keys.First();//获取当前使用中的最小的位置
                //int lastk = RecevieingOffList.Keys.Last();
                //if ((first < AddrOffsetStart && lastk > AddrOffsetStart)
                //    ||(
                    
                //    ))
                //{ 
    
                    
                //}
                ArraySegment<byte> partBuffer = new ArraySegment<byte>(buffer, AddrOffsetStart, length);
                //RecevieingOffList.Add(partBuffer.Offset, partBuffer);
                //var lastoff = lastk + RecevieingOffList[lastk].Count;
    
                return partBuffer;
                //return new ArraySegment<byte>(buffer, CurOffSet, length);
            }
    
    
            //Stack<ArraySegment<byte>> Pool = new Stack<ArraySegment<byte>>();
    
    
            public IList<ArraySegment<byte>> SendBuffer
            {
                get
                {
                    if (CurOffSet > LastSendOffSet)//如果当前缓冲区位置大于最后发送的位置,那么直接返回 上一次最后发送到的位置到当前
                    {
                        int curOffset = CurOffSet;
                        var list = new List<ArraySegment<byte>> { new ArraySegment<byte>(buffer, LastSendOffSet, curOffset) };
                        LastSendOffSet = curOffset;
                        return list ;
                    }
                    else if (CurOffSet < LastSendOffSet)
                    {
    
                    }
                    else
                    {
                        return null;
                    }
                }
            }
    
  • 相关阅读:
    关于Unity中Mecanim动画的重定向与动画混合
    php远程抓取网站图片并保存
    OpenResty最佳实践
    111
    安装Nginx+Lua+OpenResty开发环境配置全过程实例
    ecshop常用的一些变量
    php 常用的标签比较
    PHP 设计模式
    mysql导入sql脚本
    linux 解压压缩大全
  • 原文地址:https://www.cnblogs.com/SHGF/p/3464602.html
Copyright © 2011-2022 走看看