c# 高效的线程安全队列ConcurrentQueue(下) Segment类
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类的更多相关文章
- c# 高效的线程安全队列ConcurrentQueue
c#高效的线程安全队列ConcurrentQueue<T>(上) c# 高效的线程安全队列ConcurrentQueue(下) Segment类 c#高效的线程安全队列Concurrent ...
- c#高效的线程安全队列ConcurrentQueue<T>(上)
ConcurrentQueue<T>队列是一个高效的线程安全的队列,是.Net Framework 4.0,System.Collections.Concurrent命名空间下的一个数 ...
- C#数据结构-线程安全队列
什么是线程安全? 答:线程安全是多线程编程时的计算机程序代码中的一个概念.在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等意 ...
- C#-----线程安全的ConcurrentQueue<T>队列
ConcurrentQueue<T>队列是一个高效的线程安全的队列,是.Net Framework 4.0,System.Collections.Concurrent命名空间下的一个数据 ...
- 线程安全的ConcurrentQueue<T>队列
队列(Queue)代表了一个先进先出的对象集合.当您需要对各项进行先进先出的访问时,则使用队列.当您在列表中添加一项,称为入队,当您从列表中移除一项时,称为出队. ConcurrentQueue< ...
- [一起读源码]走进C#并发队列ConcurrentQueue的内部世界
决定从这篇文章开始,开一个读源码系列,不限制平台语言或工具,任何自己感兴趣的都会写.前几天碰到一个小问题又读了一遍ConcurrentQueue的源码,那就拿C#中比较常用的并发队列Concurren ...
- 线程池 队列 synchronized
线程池 BlockingQueue synchronized volatile 本章从线程池到阻塞队列BlockingQueue.从BlockingQueue到synchronized 和 volat ...
- 生产消费模式:多线程读写队列ConcurrentQueue
需求:现需要将多个数据源的数据导入到目标数据库,这是一个经典的生产消费应用的例子. 直接上代码,看下实现: // 初始化列队缓冲区 队列大小为100 IDataCollection<List&l ...
- Linux多线程系列-2-条件变量的使用(线程安全队列的实现)
多线程情况下,往往需要使用互斥变量来实现线程间的同步,实现资源正确共享. linux下使用如下变量和函数 //条件变量 pthread_cond_t int pthread_cond_init (pt ...
随机推荐
- Mapreduce读取Hbase表,写数据到一个Hbase表中
public class LabelJob { public static void main(String[] args) throws Exception { Job job = Job.getI ...
- 20150926kaggle Titanic入门篇excel&python
1 excel数据透视表 这里主要是讲述了一下插入里面的数据透视表常用功能,数据透视表十分方便,比直接筛选还要简单,看数据很直观,这里大力推荐. 2 python&pandas 这里主要是讲述 ...
- css 样式大全
字体属性:(font) 大小 {font-size: x-large;}(特大) xx-small;(极小) 一般中文用不到,只要用数值就可以,单位:PX.PD 样式 {font-style: obl ...
- string 与char* char[]之间的转换 2015-04-09 11:30 29人阅读 评论(0) 收藏
1.首先必须了解,string可以被看成是以字符为元素的一种容器.字符构成序列(字符串).有时候在字符序列中进行遍历,标准的string类提供了STL容器接口.具有一些成员函数比如begin().en ...
- Swift项目兼容Objective-C问题汇总
Swift项目兼容Objective-C问题汇总 转载自 http://www.cocoachina.com/swift/20150608/12025.html 本文是投稿文章,作者:一叶(博客)欢迎 ...
- IIS 7 WAS服务不可用
在 Windows Server 2008 上使用 %windir%\system32\inetsrv\appcmd.exe list wp 命令,得到如下错误: ERROR ( message:WA ...
- Spring REST实践之客户端和测试
RestTemplate 可参考spring实战来写这部分. RestTemplate免于编写乏味的样板代码,RestTemplate定义了33个与REST资源交互的方法,涵盖了HTTP动作的各种形式 ...
- Windows下使用NIF扩展Erlang方法
在Erlang中,NIF(Native Implemented Function)被用来扩展erlang的某些功能,一般用来实现一些erlang很难实现的,或者一些erlang实现效率不高的功能. N ...
- Animation Spinner【项目】
https://github.com/vjpr/healthkick/blob/master/src/win/healthkick/ucSpinnerCogs.xaml 网上的例子,放在UserCon ...
- (剑指Offer)面试题21:包含min函数的栈
题目: 定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数. 在该栈中,调用min,push,pop的时间复杂度都是O(1) 思路: 1.除了原来的栈s,增加一个辅助栈s_min,用 ...