程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> Visual Basic語言 >> VB.NET >> 游戲大廳從基礎開始(8)--繞回來細說聊天室(下)垃圾列表

游戲大廳從基礎開始(8)--繞回來細說聊天室(下)垃圾列表

編輯:VB.NET

前情回顧 我們的最初的需求是建立一個拉模式下用戶暫存的順序信息池

還是這張工作模式圖 我們可以把這個需求設計為

Clear:清除所有內容

GetEnumerator :實現枚舉器,新向舊方向的順序枚舉,這樣一旦到達上次讀取的時間就可以中斷 枚舉。

RecycleFromButtom:從舊向前進行搜索 把滿足條件的扔到GC

StackOn :把一個新 信息放在堆棧的頂部

這就好像是一個舊報紙回收傳送帶,一群人在焚燒之前看看還有沒有什麼值 得保存的信息 排個照,存個檔,沒有用的就直接扔進焚化爐。

實現設計

根據上一章的研 究結果 我們需要一個能夠在寫的同時 能夠完全無鎖並發訪問的順序數據池

看起來基於 Array的 任何數據結構都不太適合並發讀。

這時候我們把目光轉向鏈表結構。

大圖 大圖

鏈表在實現聊天室時 得天獨厚

姑且我們為垃圾列表建立這樣一個鏈表節點

public void StackOn(  IRecycleNode<T>  newOne)
{
 _lock.EnterWriteLock ();
 newOne.Lower = newOne.Higher = null;
 if (_Top != null)
 {
  _Top.Higher = newOne;
  newOne.Lower = _Top;
  _Top = newOne;

 }
 else
  {
   _Top =newOne  ;
   _Bottom = _Top;
  }
 newOne.TimeStamp = DateTime.Now;
 _lock.ExitWriteLock();
}

我們以此作 為基礎繼續討論。

關於枚舉器並發訪問

相比循環隊列中我們MoveNext的時候需要的 _size, _head, _index 和array中元素 這幾個變量隨時可能產生的並發沖突

public  bool MoveNext()
{
 if (this._version != this._q._version)
 {
  ThrowHelper.ThrowInvalidOperationException (ExceptionResource.InvalidOperation_EnumFailedVersion);
 }
 if (this._index == -2)
 {
  return false;
 }
 this._index++;
 if (this._index == this._q._size)
 {
  this._index = -2;
  this._currentElement = default(T);
  return false;
 }
 this._currentElement = this._q.GetElement(this._index);
 return true;
}

Queue:

internal T GetElement(int i)
{
 return this._array[(this._head + i) % this._array.Length];
}

在MoveNext的時候 我們的RecycleList訪問的是一個不會髒的引用 : Lower

public bool MoveNext()
{
 if (!startedFlag)
 {
  startedFlag =true ;
  return (_beginNode != null);

 };
 var cl = _currentNode.Lower;
 if (cl != null)
 {
   _currentNode = cl;
  return true;
 }
 else
  return false;
}

不沖突 就是不沖突~

關於並發回收

鏈表回收相當的簡單, node. Lower=null;

一旦node的lower設置為 null 那麼下面的所有節點就脫離了GCRoot 就可以被回收了

如果別的線程正在其下的_Bottom檢查回收, 由於 Higher的聯系仍然沒斷,向上的枚舉仍然可以進行

public void RecycleFromButtom(Func<IRecycleNode<T>, bool>  RecycleCondition)
{
 var bn = _Bottom;
 //if (_Bottom == null) _Bottom = ;
 var bh = bn;
 if (bh != null) bh = bh.Higher;
 while (bn != null & bh != null)
 {
  if (RecycleCondition(bn))
   {
    bh.Lower = null;
   }
  _Bottom = bh;
  bn = _Bottom;
  bh = bn.Higher;

 }

}

_Bottom 決定了GC能夠回收的最後一個節點。 它不需要安全。 就算它被指定為 實際底部下 面的其他節點 也僅僅使一兩個節點苟延殘喘一個周期。

唯一的迷你鎖:StackOn

理論上 的完全無鎖 被破壞在寫入這一關。

由於在鏈表頭部增加節點並不是原子操作,所以這裡必須增 加一個寫入鎖

這個鎖非常非常的小 :

public void StackOn(  IRecycleNode<T>  newOne)
{
 _lock.EnterWriteLock ();
 newOne.Lower = newOne.Higher = null;
 if (_Top != null)
 {
  _Top.Higher = newOne;
  newOne.Lower = _Top;
  _Top = newOne;

 }
 else
 {
  _Top =newOne  ;
  _Bottom = _Top;
 }
 newOne.TimeStamp = DateTime.Now;
 _lock.ExitWriteLock();
}

由於 對_top的修改是原子性的

_Top.Higher = newOne;

newOne.Lower = _Top;

_Top = newOne;

在創建Enumertor的時候 完全可以髒讀 ————沒有人在意自己讀取的是最上面一條信息 還是第二個信息 他們只關心 是否能讀下去

只要我們的ChatMessage 實現 IRecycleNode,我們就可以把它放進這個池中了

namespace WayneGameSolution.Chat
{

 public class  ChatMessage : IChatMessage, IRecycleNode<IChatMessage>
    {

 public ChatMessage()
        { }

 #region  IChatMessage Members

 public string ChannelID
  {
   get;
   set;
  }

 public string ChannelName
  {
   get;
   set;
  }

 public string ChaterFrom
  {
   get;
   set;
  }

 public string ChaterTo
  {
   get;
   set;
  }

 public MessageRenderType RenderType
  {
   get;
   set;
  }

 public string Text
  {
   get;
   set;
  }

 public DateTime TimeStamp
  {
   get;
   set;
  }


  #endregion

 #region ICloneable Members

 public object Clone()
  {
   return MemberwiseClone();
  }

 #endregion

 #region  IRecycleNode<IChatMessage> Members

 public  IRecycleNode<IChatMessage> Lower
  {
   get;
   set;
  }

 public IRecycleNode<IChatMessage> Higher
  {
   get;
   set;
  }

 public IChatMessage Value
  {
   get
   {
    return this;
   }
   set
   {
    throw new NotImplementedException();
   }
  }

 #endregion
    }
}

垃圾列表最終定稿

RecycleList

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Threading;
using  System.Security.Permissions;

namespace  System.Collections.Generic.Sync
{
    public class RecycleList<T> :  IEnumerable<T>
    {
         System.Threading.ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
         IRecycleNode<T> _Bottom, _Top;
        //public  IRecycleNode<T> Top
        //{
        //    get
        //    {
        //        _lock.EnterReadLock ();
        //        var t = _Top;
        //         _lock.ExitReadLock();
        //        return t;

 //    }
        //}

 public void Clear()
         {
            _lock.EnterWriteLock();
             _Top = null;
            _lock.ExitWriteLock();
        }

 public void StackOn( IRecycleNode<T>  newOne)
         {
            _lock.EnterWriteLock ();
             newOne.Lower = newOne.Higher = null;
            if (_Top != null)
            {
                _Top.Higher =  newOne;
                newOne.Lower = _Top;
                 _Top = newOne;

 }
            else
             {
                 _Top =newOne  ;
                  _Bottom = _Top;
            }
             newOne.TimeStamp = DateTime.Now;
             _lock.ExitWriteLock();
        }

 public void RecycleFromButtom (Func<IRecycleNode<T>, bool> RecycleCondition)
        {
             var bn = _Bottom;
            //if (_Bottom ==  null) _Bottom = ;
            var bh = bn;
             if (bh != null) bh = bh.Higher;
            while (bn !=  null & bh != null)
            {
                 if (RecycleCondition(bn))
                {
                         bh.Lower = null;
                }
                _Bottom = bh;
                 bn = _Bottom;
                bh = bn.Higher;

 }

 }

 #region IEnumerable<T> Members
        public  IEnumerator<T> GetEnumerator()
        {
             return new RecycleListEnumerator<T>(_Top);
        }

  #endregion

 #region IEnumerable Members

 IEnumerator  IEnumerable.GetEnumerator()
        {
            return new  RecycleListEnumerator<T>(_Top);
        }

 #endregion

 }

 public interface IRecycleNode<T>
     {
        IRecycleNode<T> Lower { get; set; }
         IRecycleNode<T> Higher { get; set; }
        T Value { get;  set; }
        DateTime TimeStamp
        {
             get;
            set;
        }
    }

 public class RecycleListEnumerator<T> : IEnumerator<T>
     {
        IRecycleNode<T> _beginNode;
         IRecycleNode<T> _currentNode;
     public       RecycleListEnumerator(IRecycleNode<T> beginNode)
        {
             _beginNode = _currentNode = beginNode;
        }
         #region IEnumerator<T> Members

 public T Current
        {
            get { return _currentNode.Value; }
        }

 #endregion

 #region IDisposable Members

 public void Dispose()
        {
             _beginNode = null;
            _currentNode = null;
         }
        #endregion

 #region IEnumerator Members

 object IEnumerator.Current
        {
            get {  return Current; }
        }
        private bool  startedFlag=false ;
        public bool MoveNext()
         {
            if (!startedFlag)
            {
                 startedFlag =true ;
                 return (_beginNode != null);

 };
            var cl =  _currentNode.Lower;
            if (cl != null)
             {
                _currentNode = cl;
                 return true;
            }
             else
                return false;
        }

 public void Reset()
        {
            _currentNode =  _beginNode;
        }

 #endregion
    }

 }

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved