Segment成员变量

long long m_index;

记录该segment的索引号。

int* volatile m_state;

状态数组,标识所对应的元素节点的状态,默认值为0,如果该元素节点添加了值,则标记为1。

T* volatile m_array;

队列元素存储空间的指针。

Segment* volatile m_next;

指向下一个segment的指针。

volatile long m_high;

标识在当前segment,元素最后添加的索引值,初始值为-1,如果该segment被填满了,则该值为SEGMENT_SIZE – 1。

volatile long m_low;

标识在当前segment,元素最后取出位置的索引值,初始值为0,如果该segment一个都没有取走元素,则该值为0。如果m_low >m_high,表示该segment为空。

Segment成员函数

void Grow(Segment* volatile* tail)

1
2
3
4
5
6
void Grow(Segment* volatile* tail)
{
    Segment* segment = new Segment(m_index + 1);
    m_next = segment;
    *tail = m_next;
}
1
创建下一个segment,并将tail指针指向新创建的segment;

bool TryAppend(T value, Segment* volatile *  tail)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
bool TryAppend(T value, Segment* volatile *  tail)
{
    if (m_high >= SEGMENT_SIZE - 1)
    {
        return false;
    }
 
    int index = SEGMENT_SIZE;
 
    index = InterlockedIncrement(&m_high);
 
    if (index <= SEGMENT_SIZE - 1)
    {
        m_array[index] = value;
        m_state[index] = 1;
    }
    if (index == SEGMENT_SIZE - 1)
    {
        Grow(tail);
    }
     
    return (index <= SEGMENT_SIZE - 1);
}

往当前segment里面,增加一个元素,如果添加满了,就创建下一个segment。

bool TryPeek(T* result)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
bool TryPeek(T* result)
{
    int low = GetLow();
    if (low > GetHigh())
    {
        return false;
    }
 
    DNetSpinWait wait;
    while (m_state[low] == 0)
    {
        wait.SpinOnce();
    }
    *result = m_array[low];
    return true;
}

如果segment为空,返回false,否则,返回low所在位置的值。

bool TryRemove(T* result, Segment* volatile * head)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
bool TryRemove(T* result, Segment* volatile * head)
{
    DNetSpinWait wait;
    int low = GetLow();
    for (int i = GetHigh(); low <= i; i = GetHigh())
    {
        if (InterlockedCompareExchange(&m_low, low + 1, low) == low)
        {  
 
            DNetSpinWait wait2;
            while (m_state[low] == 0)
            {
                wait2.SpinOnce();
            }
            *result = m_array[low];
            if ((low + 1) >= SEGMENT_SIZE)
            {
                wait2.Reset();
                while (m_next == NULL)
                {
                    wait2.SpinOnce();
                }
                *head = m_next;
            }
            return true;
        }
        wait.SpinOnce();
        low = GetLow();
    }
    result = NULL;
    return false;
}

这是最复杂的一个方法。利用了InterlockedCompareExchange方法,该方法的解释:
LONG __cdecl InterlockedCompareExchange(
  __inout  LONG volatile* Destination,
  __in     LONG Exchange,
  __in     LONG Comparand
);
Parameters
Destination 
A pointer to the destination value. The sign is ignored.

Exchange 
The exchange value. The sign is ignored.

Comparand 
The value to compare to Destination. The sign is ignored.

Return Value
The function returns the initial value of the Destination parameter.

通过自旋来保证线程同步。

int GetHigh()


    return min(m_high, SEGMENT_SIZE - 1);
}

bool IsEmpty()

{
    return m_low > m_high;
}

int GetLow()


    return min(m_low, SEGMENT_SIZE);
}

Segment* GetNext()

{
    return m_next;
}

long long GetIndex()

{
    return m_index;
}

c# 高效的线程安全队列ConcurrentQueue(下) Segment类的更多相关文章

  1. c# 高效的线程安全队列ConcurrentQueue

    c#高效的线程安全队列ConcurrentQueue<T>(上) c# 高效的线程安全队列ConcurrentQueue(下) Segment类 c#高效的线程安全队列Concurrent ...

  2. c#高效的线程安全队列ConcurrentQueue<T>(上)

      ConcurrentQueue<T>队列是一个高效的线程安全的队列,是.Net Framework 4.0,System.Collections.Concurrent命名空间下的一个数 ...

  3. C#数据结构-线程安全队列

    什么是线程安全? 答:线程安全是多线程编程时的计算机程序代码中的一个概念.在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等意 ...

  4. C#-----线程安全的ConcurrentQueue<T>队列

     ConcurrentQueue<T>队列是一个高效的线程安全的队列,是.Net Framework 4.0,System.Collections.Concurrent命名空间下的一个数据 ...

  5. 线程安全的ConcurrentQueue<T>队列

    队列(Queue)代表了一个先进先出的对象集合.当您需要对各项进行先进先出的访问时,则使用队列.当您在列表中添加一项,称为入队,当您从列表中移除一项时,称为出队. ConcurrentQueue< ...

  6. [一起读源码]走进C#并发队列ConcurrentQueue的内部世界

    决定从这篇文章开始,开一个读源码系列,不限制平台语言或工具,任何自己感兴趣的都会写.前几天碰到一个小问题又读了一遍ConcurrentQueue的源码,那就拿C#中比较常用的并发队列Concurren ...

  7. 线程池 队列 synchronized

    线程池 BlockingQueue synchronized volatile 本章从线程池到阻塞队列BlockingQueue.从BlockingQueue到synchronized 和 volat ...

  8. 生产消费模式:多线程读写队列ConcurrentQueue

    需求:现需要将多个数据源的数据导入到目标数据库,这是一个经典的生产消费应用的例子. 直接上代码,看下实现: // 初始化列队缓冲区 队列大小为100 IDataCollection<List&l ...

  9. Linux多线程系列-2-条件变量的使用(线程安全队列的实现)

    多线程情况下,往往需要使用互斥变量来实现线程间的同步,实现资源正确共享. linux下使用如下变量和函数 //条件变量 pthread_cond_t int pthread_cond_init (pt ...

随机推荐

  1. 使用gdb调试多线程程序总结

    转:使用gdb调试多线程程序总结 一直对GDB多线程调试接触不多,最近因为工作有了一些接触,简单作点记录吧. 先介绍一下GDB多线程调试的基本命令. info threads 显示当前可调试的所有线程 ...

  2. 从一个简单的Java单例示例谈谈并发

    一个简单的单例示例 单例模式可能是大家经常接触和使用的一个设计模式,你可能会这么写 public class UnsafeLazyInitiallization { private static Un ...

  3. 开着奥迪做Uber司机是什么心态?

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  4. 类似于QQ游戏百万人同时在线的服务器架构实现

    http://blog.csdn.net/sodme/article/details/213995 —————————————————————————————————————————————————— ...

  5. socket对于大数据的发送和接收

    大数据是指大于32K或者64K的数据. 大数据的发送和接收通过TSTREAM对象来进行是非常方便的. 我们把大数据分割成一个个4K大小的小包,然后再依次传输. 一.大数据的发送的类语言描述: 1)创建 ...

  6. oracle不用tsname文件的时候着怎么办

    oracle\product\10.2.0\client_2\odp.net\PublisherPolicy\Policy.9.2.Oracle.DataAccess.config 找到newVers ...

  7. CodeForces 709C Letters Cyclic Shift (水题)

    题意:给定一个字符串,让你把它的一个子串字符都减1,使得总字符串字典序最小. 析:由于这个题是必须要有一个字串,所以你就要注意这个只有一个字符a的情况,其他的就从开始减 1,如果碰到a了就不减了,如果 ...

  8. c++,windows中的字符问题

    string与char*的转换方法 string a; char *b=a.c_str(); string a=new String(b); a=b; LPCWSTR是unicode的字符串,LPCS ...

  9. opencv直方图均衡化

    #include <iostream> #include "highgui.h" #include "cv.h" #include "cx ...

  10. C:指针、数据类型、格式化输入输出、输入函数的坑点

    指针.数据类型.格式化输入输出.输入函数的坑点 有时候我们迷茫的时候,坚持就是最好的选择. 1.指针的分类为什么很重要? 参考 答:因为指针会根据相应的类型取对应长度的数据,类型决定所取数据的长度.如 ...