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 ...
随机推荐
- MySql 5.6 慢查询
网上都巨坑 最后在官网找到了开启方法 原来是配置文件改了 Updated example for 2015 MySQL 5.6: slow_query_log = 1slow_query_log_fi ...
- 云计算分布式大数据Hadoop实战高手之路第七讲Hadoop图文训练课程:通过HDFS的心跳来测试replication具体的工作机制和流程
这一讲主要深入使用HDFS命令行工具操作Hadoop分布式集群,主要是通过实验的配置hdfs-site.xml文件的心跳来测试replication具体的工作和流程. 通过HDFS的心跳来测试repl ...
- bzoj3714: [PA2014]Kuglarz
[PA2014]KuglarzTime Limit: 20 Sec Memory Limit: 128 MBSubmit: 553 Solved: 317[Submit][Status][Discus ...
- jszs 对象引用
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- SharePoint咨询师之路:设计之前的那些事四:负载均衡 - web服务器
提示:本系列只是一个学习笔记系列,大部分内容都可以从微软官方网站找到,本人只是按照自己的学习路径来学习和呈现这些知识.有些内容是自己的经验和积累,如果有不当之处,请指正. 容量管理 规模 体系结构 ...
- Java基础String类
String是一个对象 String不属于8种基本数据类型(byte, char, short, int, float, long, double, boolean),String是对象,所以其默认值 ...
- C#判断当前操作系统
private OperatingSystem os = System.Environment.OSVersion; os.Version.Major.ToString(); ) { //Win7系统 ...
- HDU 5778 abs (素数,暴力)
题意:给定一个数x,求正整数y≥2y\geq 2y≥2,使得满足以下条件: 1.y-x的绝对值最小 2.y的质因数分解式中每个质因数均恰好出现2次. 析:由于y质因数分解式中每个质因数均出现2次,那么 ...
- HDU 5074 Luck Competition (暴力,概率)
题意:有 n 个人参加比赛,给出n-1个人的成绩,然后要选出一个幸运的人,先把所有的分数求平均数,然后再*2/3,那个不大于这个数,且最接近的数,就是最幸运的, 让你设置最后一个人的分,使他是最幸运的 ...
- JAVA网站高并发解决方案
一个小型的网站,比如个人网站,可以使用最简单的html静态页面就实现了,配合一些图片达到美化效果,所有的页面均存放在一个目录下,这样的网站对系统架构.性能的要求都很简单,随着互联网业务的不断丰富,网站 ...