首页 新闻 会员 周边 捐助

关于Segment<T>的实现

0
悬赏园豆:20 [已解决问题] 解决于 2013-01-23 10:51

最近在研究ConcurrentQueue<T>的实现,发现里面有个私有类Segment<T>,拿Reflector看了下,其中有如下的代码:

 1   internal List<T> ToList(int start, int end)
 2     {
 3         List<T> list = new List<T>();
 4         for (int i = start; i <= end; i++)
 5         {
 6             SpinWait wait = new SpinWait();
 7             while (this.m_state[i] == null)
 8             {
 9                 wait.SpinOnce();
10             }
11             list.Add(this.m_array[i]);
12         }
13         return list;
14     }

this.m_state[i] == null,这句中的m_state[i]是一个整形数组,为什么会有这种奇怪的判断方式?this.m_state[i]的值不是一个整数么,什么时候会有null的情况出现?

 

另外有如下代码片段:

 1 try
 2         {
 3         }
 4         finally
 5         {
 6             index = Interlocked.Increment(ref this.m_high);
 7             if (index <= 0x1f)
 8             {
 9                 this.m_array[index] = value;
10                 this.m_state[index] = 1;
11             }
12             if (index == 0x1f)
13             {
14                 this.Grow(ref tail);
15             }
16         }

为什么将try留空,而将实现放在finally里面,这种写法有什么特别的作用么?感觉颠覆了我写代码的常识了,求高人解惑

garry的主页 garry | 菜鸟二级 | 园豆:495
提问于:2013-01-22 16:01
< >
分享
最佳答案
1

第一个是反编译问题,正如上面的人所说。第二个问题详解看这里。简单来说就是因为这里是多线程环境,因此任何时候都有可能会引发ThreadAbortException,如果是在try块里那么某些代码不能保证被执行。而finally块则可以保证即使是发生了ThreadAbortException,这些代码也会被执行。这是一个小技巧,不过现在已经不适用了,更好的替代方式是Thread.BeginCritialRegeion

收获园豆:10
水牛刀刀 | 大侠五级 |园豆:6350 | 2013-01-23 09:14

非常感谢,链接中的文章很给力,解决了我的疑惑.

garry | 园豆:495 (菜鸟二级) | 2013-01-23 10:49
其他回答(3)
0

int在用户在建立字段的时候如果int?这个样子的话,那么int默认就是null。

至于为什么写在finally里面,我感觉没有什么意义。

rains | 园豆:860 (小虾三级) | 2013-01-22 16:08
1

你的反编译有问题吧:

// System.Collections.Concurrent.ConcurrentQueue<T>.Segment
internal List<T> ToList(int start, int end)
{
    List<T> list = new List<T>();
    for (int i = start; i <= end; i++)
    {
        SpinWait spinWait = default(SpinWait);
        while (this.m_state[i] == 0)
        {
            spinWait.SpinOnce();
        }
        list.Add(this.m_array[i]);
    }
    return list;
}


try{}finally{} 有个很大的作用,就是保证 finally 块中的代码总是被执行,虽然这里 try 块里面没有任何代码,但是这种写法可以保证 Unhandled Exception 触发时,finally 块中的代码仍然会被执行。

收获园豆:5
Launcher | 园豆:45050 (高人七级) | 2013-01-22 16:13

try里面没有任何代码的话,有什么可能性会触发Exception,反而是在finally里面放了那么多代码,要是引发Exception的话程序不就崩掉了?

支持(0) 反对(0) garry | 园豆:495 (菜鸟二级) | 2013-01-22 18:28

@garry: Unhandled Exception (http://msdn.microsoft.com/en-us/magazine/cc793966.aspx)不是由当前执行代码引发的,它可能是由应用程序域中其它线程引发的。当发生 Unhandled Exception 后,finally 块中代码的执行依赖于什么样的异常操作被触发。也就是说,如果异常不能在本地捕捉到,则首先运行 finally 块中的代码,然后再向上一级去搜索一个匹配的异常处理程序并运行。

写在 finally 块中的代码是经过精心设计的,通常这些代码不会触发异常。

支持(0) 反对(0) Launcher | 园豆:45050 (高人七级) | 2013-01-23 09:28

@garry: MSDN对 finally 还有个解释,这里的直接原因不是多线程的问题,而是发生了 Unhandled Exception (这可能是 OS 异常)后,如何处理 finally 中代码块的问题,根据 OS 的设置,finally 中代码可能不会被执行。在 OS 看来,出现错误后会设置一个中断,CLR 根据中断的类型和位置做对应的处理,又或者无法处理直接卸载整个进程。

支持(0) 反对(0) Launcher | 园豆:45050 (高人七级) | 2013-01-24 10:18

@Launcher: 非常感谢你的解释,总段弄明白了

支持(0) 反对(0) garry | 园豆:495 (菜鸟二级) | 2013-01-26 12:13
1

我也觉得是反编译问题,用dotpeek比较好

收获园豆:5
凹出来 | 园豆:33 (初学一级) | 2013-01-22 16:22

坑爹呀,用dotpeek看了下,果然是反编译有问题,Reflector怎么会有这种低级错误啊

支持(0) 反对(0) garry | 园豆:495 (菜鸟二级) | 2013-01-22 18:36
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册