惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
Stack Overflow Blog
Stack Overflow Blog
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
T
The Blog of Author Tim Ferriss
博客园 - 叶小钗
N
Netflix TechBlog - Medium
腾讯CDC
C
Check Point Blog
P
Proofpoint News Feed
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI
S
SegmentFault 最新的问题
F
Fortinet All Blogs
美团技术团队
U
Unit 42
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 司徒正美
F
Full Disclosure
Recorded Future
Recorded Future
D
DataBreaches.Net
博客园 - 【当耐特】
Martin Fowler
Martin Fowler
J
Java Code Geeks
I
InfoQ
Y
Y Combinator Blog
A
About on SuperTechFans
AI
AI
爱范儿
爱范儿
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Forbes - Security
Forbes - Security
W
WeLiveSecurity
M
MIT News - Artificial intelligence
雷峰网
雷峰网
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Simon Willison's Weblog
Simon Willison's Weblog
Schneier on Security
Schneier on Security
The GitHub Blog
The GitHub Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
aimingoo的专栏
aimingoo的专栏
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
G
GRAHAM CLULEY
Know Your Adversary
Know Your Adversary
Latest news
Latest news
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
D
Docker
Recent Commits to openclaw:main
Recent Commits to openclaw:main
量子位
V2EX - 技术
V2EX - 技术
Project Zero
Project Zero

博客园 - MSFT:waywa 韦恩卑鄙

[UWP]一种利用Behavior 将StateTrigger集中管理的方案 【干货】个人工作文档节选:XAML MVVM 框架易用性细节优化Tips MVVM Sidekick Win8 RT 轻量级MVVM框架开源 对资源加读写锁的容器 对不能用using的成对操作,快速扩展IDisposable的方法 intel I7平台Win7 x64 下wpf、silverlight 与aero特效动画缓慢故障排除一则 今天被Prism里面的一段代码雷到了 1080*1920 下看网站很爽 游戏大厅 从基础开始(7)--绕回来细说聊天室(中间偏下)之女仆编年史2 游戏大厅 从基础开始(6)--绕回来细说聊天室(中)之女仆编年史1 - MSFT:waywa 韦恩卑鄙 游戏大厅 从基础开始(5)--绕回来细说聊天室(上) 简单的树遍历枚举器v0.2-挑战一个程序员到底能多懒- 添加广度优先遍历 一时技痒 不用模拟第一印象的构造 通过三个观察得来的规律解决N^2个往返接力问题 游戏大厅 从基础开始(4)-通过L2X用配置文件反射组装程序(VB only) 关于silverlight depencyobject简单的clone silver light 2 客户端的伪DataTable for EF X360吉他英雄4鼓套装 &1 TB硬盘入手 游戏大厅 从基础开始(3.5)——最吸引眼球的部分 客户端与服务器的连接 的实现 游戏大厅 从基础开始(3)——最吸引眼球的部分 客户端与服务器的连接
游戏大厅 从基础开始(8)--绕回来细说聊天室(下)垃圾列表
MSFT:waywa 韦恩卑鄙 · 2009-08-27 · via 博客园 - MSFT:waywa 韦恩卑鄙

没错,这次章节没有女仆。

前情回顾

我们的最初的需求是建立一个拉模式下用户暂存的顺序信息池

还是这张工作模式图 我们可以把这个需求设计为

  • 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,我们就可以把它放进这个池中了

Code

垃圾列表最终定稿

RecycleList

这里提供一个 MVC的测试聊天室  包括所有源代码

下载

大厅源代码正在googlecode 上用c#缓慢重建   有兴趣的可以下载

wgs-game-lobby.googlecode.com

 聊天室

连接:

游戏大厅 从基础开始(1)——最简单的关系,用户与房间

游戏大厅 从基础开始(2)——最基础的交流:聊天

游戏大厅 从基础开始(3)——最吸引眼球的部分 客户端与服务器的连接

游戏大厅 从基础开始(3.5)——最吸引眼球的部分 客户端与服务器的连接 的实现  

游戏大厅 从基础开始(4)-通过L2X用配置文件反射组装程序(VB only)

游戏大厅 从基础开始(5)--绕回来细说聊天室(上)

游戏大厅 从基础开始(6)--绕回来细说聊天室(中)之女仆编年史1

游戏大厅 从基础开始(7)--绕回来细说聊天室(中间偏下)之女仆编年史2 

游戏大厅 从基础开始(8)--绕回来细说聊天室(下)垃圾列表