c#高效的线程安全队列ConcurrentQueue<T>(上)
ConcurrentQueue<T>队列是一个高效的线程安全的队列,是.Net Framework 4.0,System.Collections.Concurrent命名空间下的一个数据结构。
ConcurrentQueue<T>数据结构
下图是ConcurrentQueue<T>数据结构的示意图:

ConcurrentQueue<T>队列由若干Segment动态构成,每个Segment是一块连续的内存Buffer,大小固定为SEGMENT_SIZE。
ConcurrentQueue<T>私有成员变量
ConcurrentQueue<T>类有三个私有成员变量:
Segment* volatile m_head;
Segment* volatile m_tail;
Segment* volatile m_base;
m_head指向第一个segment,m_tail指向最后一个segment。这两个指针指向的对象,随着入队列和出队列操作而不断变化。
m_base指针固定指向ConcurrentQueue<T>实例化的第一个Segment,在析构ConcurrentQueue<T>对象时使用。
ConcurrentQueue<T>成员方法
void Enqueue(T item)
|
1
2
3
4
5
6
7
8
|
void Enqueue(T item){ DNetSpinWait wait; while (!m_tail->TryAppend(item, &m_tail)) { wait.SpinOnce(); }} |
|
1
|
从m_tail指向的segment中,加入item的值,直到成功加入,函数返回。 |
该函数会在分配了新的segment后,更新m_tail指针。
bool TryDequeue(T* result)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
bool TryDequeue(T* result){ while (!IsEmpty()) { if (m_head->TryRemove(result, &m_head)) { return true; } } result = NULL; return false;} |
如果当前队列为空,返回false,否则返回队列的第一个元素。
bool TryPeek(T* result)
|
1
2
3
4
5
6
7
8
9
10
11
12
|
bool TryPeek(T* result){ while (!IsEmpty()) { if (m_head->TryPeek(result)) { return true; } } result = NULL; return false;} |
跟TryDequeue()方法相似。
int Count()
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
int Count() { Segment* segment; Segment* segment2; int num; int num2; GetHeadTailPositions(&segment, &segment2, &num, &num2); if (segment == segment2) { return ((num2 - num) + 1); } int num3 = SEGMENT_SIZE - num; num3 += SEGMENT_SIZE * (((int) (segment2->GetIndex() - segment->GetIndex())) - 1); return (num3 + (num2 + 1));} |
通过得到当前首尾的segment指针,以及首指针的m_low索引,以及尾指针的m_high索引,计算当前队列中元素的个数。
该方法用到了GetHeadTailPositions方法。
bool IsEmpty()
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
bool IsEmpty(){ Segment* head = m_head; if (head->IsEmpty()) { if (head->GetNext() == NULL) { return true; } DNetSpinWait wait; while (head->IsEmpty()) { if (head->GetNext() == NULL) { return true; } wait.SpinOnce(); head = m_head; } } return false;} |
判定当前队列为空有两个条件,第一,m_head指向的segment为空;第二,m_head->GetNext()也为空,即m_head和m_tail指向同一个segment。
void Reset()
|
1
2
3
4
5
|
void Reset(){ DeleteNodes(); m_base = m_head = m_tail = new Segment(0);} |
重置ConcurrentQueue<T>对象,删除已经分配了的segment,并重新更新成员变量的值。
void GetHeadTailPositions(Segment** head, Segment** tail, int* headLow, int* tailHigh)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
void GetHeadTailPositions(Segment** head, Segment** tail, int* headLow, int* tailHigh){ *head = m_head; *tail = m_tail; *headLow = (*head)->GetLow(); *tailHigh = (*tail)->GetHigh(); DNetSpinWait wait; while ((((*head != m_head) || (*tail != m_tail)) || ((*headLow != (*head)->GetLow()) || (*tailHigh != (*tail)->GetHigh()))) || ((*head)->GetIndex() > (*tail)->GetIndex())) { wait.SpinOnce(); *head = m_head; *tail = m_tail; *headLow = (*head)->GetLow(); *tailHigh = (*tail)->GetHigh(); }} |
该函数就是将队列当前的m_head, m_tail指针以及m_head的m_low索引,m_tail的m_high索引取出来,放到线程栈上。并且在取出这些值后,再判断这些值是否合法。
c#高效的线程安全队列ConcurrentQueue<T>(上)的更多相关文章
- c# 高效的线程安全队列ConcurrentQueue
c#高效的线程安全队列ConcurrentQueue<T>(上) c# 高效的线程安全队列ConcurrentQueue(下) Segment类 c#高效的线程安全队列Concurrent ...
- c# 高效的线程安全队列ConcurrentQueue(下) Segment类
Segment成员变量 long long m_index; 记录该segment的索引号. int* volatile m_state; 状态数组,标识所对应的元素节点的状态,默认值为0,如果该元素 ...
- 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 ...
- C#数据结构-线程安全队列
什么是线程安全? 答:线程安全是多线程编程时的计算机程序代码中的一个概念.在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等意 ...
- Linux多线程系列-2-条件变量的使用(线程安全队列的实现)
多线程情况下,往往需要使用互斥变量来实现线程间的同步,实现资源正确共享. linux下使用如下变量和函数 //条件变量 pthread_cond_t int pthread_cond_init (pt ...
随机推荐
- flex之组件简单应用
1. 将父窗体的内容传递给子窗体: 2.将子窗体内容传递给父窗体:即用户名和密码,t1是父窗体文本框id.
- HW7.16
import java.util.Arrays; public class Solution { public static void main(String[] args) { int row = ...
- 在IT网站上少花些时间
我自己关注的IT网站还是蛮多的,经常去的有CSDN,博客园,51CTO,InfoQ,还有微博,微信上关注了IT程序猿,IT技术博客大学习,程序员之家, 开发者头条,还有还有,我还通过邮件订阅了码家周刊 ...
- 【转】MySQL日期时间函数大全
MySQL日期时间函数大全 1.DAYOFWEEK(date) 返回日期date是星期几(1=星期天,2=星期一,……7=星期六,ODBC标准)mysql> select DAYOFWEEK( ...
- css斜线
斜线 .demo{ display: inline-block; width: 400px; height: 100px; resize: both; overflow: auto; margin-t ...
- ACM 中常用的算法有哪些? 2014-08-21 21:15 40人阅读 评论(0) 收藏
ACM 中常用的算法有哪些?作者: 张俊Michael 网络上流传的答案有很多,估计提问者也曾经去网上搜过.所以根据自己微薄的经验提点看法. 我ACM初期是训练编码能力,以水题为主(就是没有任何算法, ...
- hdu 4289 Control(最小割 + 拆点)
http://acm.hdu.edu.cn/showproblem.php?pid=4289 Control Time Limit: 2000/1000 MS (Java/Others) Mem ...
- c# 解决IIS写Excel的权限问题
c# 解决IIS写Excel的权限问题 from: http://www.jb51.net/article/31473.htm 发布:mdxy-dxy 字体:[增加 减小] 类型:转载 使用以上方法必 ...
- java使用org.apache.poi读取与保存EXCEL文件
一.读EXCEL文件 package com.ruijie.wis.cloud.utils; import java.io.FileInputStream; import java.io.FileNo ...
- UI:页面传值、单例模式传值、属性传值、NSUserDefaults 数据持久化
<单页面传值> 页面传值,从前向后传值,使用属性,在后一个页面定义属性,在前一个页面,用点语法,获得值,在适当的时候传值 页面传值,从后向前面传值,使用协议和代理,在后一个页面指定协议,定 ...