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

推荐订阅源

Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
云风的 BLOG
云风的 BLOG
美团技术团队
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
爱范儿
爱范儿
Stack Overflow Blog
Stack Overflow Blog
WordPress大学
WordPress大学
GbyAI
GbyAI
雷峰网
雷峰网
P
Proofpoint News Feed
IT之家
IT之家
人人都是产品经理
人人都是产品经理
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
aimingoo的专栏
aimingoo的专栏
小众软件
小众软件
T
The Blog of Author Tim Ferriss
月光博客
月光博客
V
Visual Studio Blog
L
LINUX DO - 热门话题
L
Lohrmann on Cybersecurity
T
Troy Hunt's Blog
Project Zero
Project Zero
U
Unit 42
T
Tor Project blog
Scott Helme
Scott Helme
L
LINUX DO - 最新话题
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
I
InfoQ
Cloudbric
Cloudbric
P
Proofpoint News Feed
The Cloudflare Blog
H
Heimdal Security Blog
Google DeepMind News
Google DeepMind News
The GitHub Blog
The GitHub Blog
Attack and Defense Labs
Attack and Defense Labs
有赞技术团队
有赞技术团队
T
Threat Research - Cisco Blogs
T
The Exploit Database - CXSecurity.com
J
Java Code Geeks
博客园 - 【当耐特】
Security Latest
Security Latest
The Register - Security
The Register - Security
F
Fortinet All Blogs
I
Intezer
H
Hackread – Cybersecurity News, Data Breaches, AI and More
MongoDB | Blog
MongoDB | Blog
N
Netflix TechBlog - Medium
NISL@THU
NISL@THU
T
Tenable Blog

博客园 - 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)--绕回来细说聊天室(下)垃圾列表