c语言 无锁编程,无锁编程与有锁编程的效率总结、无锁队列的实现(c语言)「建议收藏」

c语言 无锁编程,无锁编程与有锁编程的效率总结、无锁队列的实现(c语言)「建议收藏」1.无锁编程与有锁编程的效率无锁编程,即通过CAS原子操作去控制线程的同步。如果你还不知道什么使CAS原子操作,建议先去查看相关资料,这一方面的资料网络上有很多。CAS实现的是硬件级的互斥,在线程低并发的情况下,其性能比普通互斥锁高效,但是当线程高并发的时候,硬件级互斥引入的代价与应用层的锁竞争产生的代价同样都是很大的。这时普通锁编程其实是优于无锁编程的。硬件级原子操作使应用层的操作变慢,而且无法…

大家好,又见面了,我是你们的朋友全栈君。

1.无锁编程与有锁编程的效率

无锁编程,即通过CAS原子操作去控制线程的同步。如果你还不知道什么使CAS原子操作,建议先去查看相关资料,这一方面的资料网络上有很多。

CAS实现的是硬件级的互斥,在线程低并发的情况下,其性能比普通互斥锁高效,但是当线程高并发的时候,硬件级互斥引入的代价与应用层的锁竞争产生的代价同样都是很大的。这时普通锁编程其实是优于无锁编程的。

硬件级原子操作使应用层的操作变慢,而且无法再进行优化。如果对有锁多线程程序有良好的设计,那么可以使程序的性能在不下降的同时,实现高并发。

2.无锁编程的好处

无锁编程不需要程序员再去考虑死锁、优先反转等棘手的问题,因此在对应用程序不太复杂,而对性能要求稍高的程序中,可以采取有锁编程。如果程序较为复杂,性能要求不高的程序中可以使用无锁编程。

3.无锁队列的实现

对于线程无锁同步方式方式的应用,我实现了一个无锁的队列。首先看一下程序的运行结果:

5389fffa2b83f4d5b2223d91bb76b263.png

程序的运行结果符合队列先进先出的特点。

关于一些细节的问题在代码中都有详细的注释,请参见代码:

#include #include#include#include#include//用链表实现队列

//节点结构

typedef struct Node

{

struct Node *next;

int data;

}node;

//队列的定义

typedef struct Queue

{

node* front;

node* rear;

}queue;

//定义一个全局的队列

queue que;

//队列的初始化操作

void QueInit(queue *que)

{

//申请一个新的节点

node *temp = (node*)malloc(sizeof(node));

assert(temp!=NULL);

temp->next=NULL;

que->front=que->rear=temp;

}

//队空判断

int QueEmpty()

{

return __sync_bool_compare_and_swap(&(que.rear),que.front,que.front);

}

//入队操作

void QuePush(int *d)

{

//申请新节点

node *temp = (node*)malloc(sizeof(node));

assert(temp!=NULL);

temp->data=*d;

//将新申请的节点利用原子操作插入到队列当中

node* p;

do

{

p = que.rear;

}

while(!__sync_bool_compare_and_swap(&(p->next),NULL,temp));

//重置尾指针

__sync_bool_compare_and_swap(&(que.rear),p,temp);

}

//出队操作

int QuePop(int *d)

{

//temp为要输出的元素

node *temp;

//因为temp可能为NULL,因此我们用P记录temp->next的值,后续会用到

node *p;

do

{

if(QueEmpty())

return 0;

temp = que.front->next;

if(temp!=NULL)

p=temp->next;

else

p=NULL;

}

while(!__sync_bool_compare_and_swap(&(que.front->next),temp,p));

//更新尾指针

__sync_bool_compare_and_swap(&(que.rear),temp,que.front);

if(temp!=NULL)

{

*d = temp->data;

free(temp);

return 1;

}

return 0;

}

//两个线程函数:一个入队,一个出队

void * thread_push(void *arg)

{

while(1)

{

int data = rand()%100;

QuePush(&data);

printf(“队列插入元素:%d\n”,data);

sleep(1);

}

}

void *thread_pop(void *arg)

{

int data;

while(1)

{

sleep(2);

if(!QuePop(&data))

printf(“队列为空\n”);

else

printf(“队列输出元素:%d\n”,data);

}

}

int main()

{

//初始化队列

QueInit(&que);

//创建两个线程

pthread_t id[2];

pthread_create(&id[0],NULL,thread_push,NULL);

pthread_create(&id[1],NULL,thread_pop,NULL);

//等待线程结束

pthread_join(id[0],NULL);

pthread_join(id[1],NULL);

//在这之后还因该删除队列回收内存

//删除队列不涉及多线程操作,不再赘述

return 0;

}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/134202.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 1,什么是ant「建议收藏」

    1,什么是antant是构建工具2,什么是构建概念到处可查到,形象来说,你要把代码从某个地方拿来,编译,再拷贝到某个地方去等等操作,当然不仅与此,但是主要用来干这个3,ant的好处跨平台–因为ant是使用java实现的,所以它跨平台使用简单–与ant的兄弟make比起来语法清晰–同样是和make相比功能强大–ant能做的事情很多,可能你用了很久,你仍然…

    2022年4月9日
  • IntelliJ IDEA 2021.4 Beta激活码(破解版激活)

    IntelliJ IDEA 2021.4 Beta激活码(破解版激活),https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月16日
  • Yii 多語言

    Yii 多語言

    2021年8月20日
  • R-L模型算法的优缺点_风筝模型公式

    R-L模型算法的优缺点_风筝模型公式介绍Logistic回归算法,名字虽带有回归,但其实是一个分类模型。输出Y=1的对数几率是由输入x的线性函数表示的模型,直接对分类的可能性进行建模,并不是直接对分类的结果(0或者1)进行建模:假设一个样本属于正样本的概率为p,则:LR模型是在线性回归的基础上,把特征进行线性组合,再把组合的结果通过一层sigmoid函数映射成结果是1或是0的概率。逻辑斯蒂回归模型的特点:…

    2022年10月13日
  • eclipseUML工具

    eclipseUML工具
    EclipseUML2008-05-0522:05
    来源:lhttp://bach.yo2.cn/articles/category/artoftechnology/page/3
    对于UML工具,我用的并不是太深入,所以仅是对几款小型umltools,以及非专业umltools稍做评价,像RationalRose这种专业uml软件就不比较了。
     
    在选择方面个人比较偏向java,eclipse,逆向工程功能.
    1.MicrosoftVi

    2022年7月12日
  • Java实现 Hello World

    Java实现 Hello WorldHelloWorld记事本手写HelloWorldeclipse编辑器从零到一实现HelloWorld记事本手写HelloWorld1.新建Hello文本文件输入以下代码eclipse编辑器从零到一实现HelloWorld

    2022年7月16日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号