






















没错,这次章节没有女仆。
还是这张工作模式图 我们可以把这个需求设计为
这就好像是一个旧报纸回收传送带,一群人在焚烧之前看看还有没有什么值得保存的信息 排个照,存个档,没有用的就直接扔进焚化炉。
根据上一章的研究结果 我们需要一个能够在写的同时 能够完全无锁并发访问的顺序数据池
看起来基于 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
不冲突 就是不冲突~
链表回收相当的简单, 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能够回收的最后一个节点。 它不需要安全。 就算它被指定为 实际底部下面的其他节点 也仅仅使一两个节点苟延残喘一个周期。
理论上的完全无锁 被破坏在写入这一关。
由于在链表头部增加节点并不是原子操作,所以这里必须增加一个写入锁
这个锁非常非常的小 :
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,我们就可以把它放进这个池中了
Code
垃圾列表最终定稿
RecycleList
这里提供一个 MVC的测试聊天室 包括所有源代码
大厅源代码正在googlecode 上用c#缓慢重建 有兴趣的可以下载
wgs-game-lobby.googlecode.com

连接:
游戏大厅 从基础开始(3)——最吸引眼球的部分 客户端与服务器的连接
游戏大厅 从基础开始(3.5)——最吸引眼球的部分 客户端与服务器的连接 的实现
游戏大厅 从基础开始(4)-通过L2X用配置文件反射组装程序(VB only)
游戏大厅 从基础开始(6)--绕回来细说聊天室(中)之女仆编年史1
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。