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

推荐订阅源

Martin Fowler
Martin Fowler
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
Troy Hunt's Blog
Latest news
Latest news
Vercel News
Vercel News
S
SegmentFault 最新的问题
V
Vulnerabilities – Threatpost
博客园 - Franky
P
Privacy International News Feed
A
Arctic Wolf
T
The Blog of Author Tim Ferriss
S
Schneier on Security
T
The Exploit Database - CXSecurity.com
P
Palo Alto Networks Blog
T
Tor Project blog
Jina AI
Jina AI
GbyAI
GbyAI
The Hacker News
The Hacker News
博客园 - 叶小钗
Google DeepMind News
Google DeepMind News
T
Threatpost
C
CERT Recently Published Vulnerability Notes
P
Proofpoint News Feed
Scott Helme
Scott Helme
WordPress大学
WordPress大学
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Microsoft Azure Blog
Microsoft Azure Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
博客园 - 司徒正美
A
About on SuperTechFans
Recorded Future
Recorded Future
爱范儿
爱范儿
L
LangChain Blog
V
V2EX
C
Cybersecurity and Infrastructure Security Agency CISA
The Cloudflare Blog
阮一峰的网络日志
阮一峰的网络日志
K
Kaspersky official blog
Webroot Blog
Webroot Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
D
DataBreaches.Net
宝玉的分享
宝玉的分享
Google Online Security Blog
Google Online Security Blog
C
Cisco Blogs
L
Lohrmann on Cybersecurity
Help Net Security
Help Net Security
AWS News Blog
AWS News Blog
M
MIT News - Artificial intelligence
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
G
GRAHAM CLULEY

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