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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • frp内网透传以及连接frp服务器

    frp内网透传以及连接frp服务器frp 服务器实操一 准备工作二 启动三 Socket 工具创建 TCP 服务器四 创建与连接 1 创建 TCPsocket2 连接 TPC 服务器一 准备工作下载 打开 再切换至该应用的路径下二 启动运行 sunny execlientid 隧道 id 三 Socket 工具创建 TCP 服务器切记这个上面设置的这个端口号 6001 要和你隧道管理界面上的本地端口号一致 本人因为没有注意 导致弄了很长的时间 四 创建与连接 1 创建 TCPsocketAT NSOCR STREAM 6

    2025年10月14日
    3
  • android scaleanimation 动画方向,Animation 动画详解(一)——alpha、scale、translate、rotate、set的xml属性及用法…[通俗易懂]

    android scaleanimation 动画方向,Animation 动画详解(一)——alpha、scale、translate、rotate、set的xml属性及用法…[通俗易懂]一、概述Android的animation由四种类型组成:alpha、scale、translate、rotate,对应android官方文档地址:《AnimationResources》alpha渐变透明度动画效果scale渐变尺寸伸缩动画效果translate画面转换位置移动动画效果rotate画面转移旋转动画效果下面我们逐个讲讲每个标签的属性及用法。动作定义文件应该存放在res/anim文…

    2022年10月9日
    5
  • strip 命令的使用方法

    strip 命令的使用方法

    2021年12月9日
    44
  • stm32蓝牙模块控制小车_51单片机蓝牙控制小车

    stm32蓝牙模块控制小车_51单片机蓝牙控制小车STM32库函数开发系列文章目录第一篇:STM32F103ZET6单片机双串口互发程序设计与实现第二篇:最简单DIY基于STM32单片机的蓝牙智能小车设计方案文章目录STM32库函数开发系列文章目录前言一、最简单DIY基于STM32单片机的蓝牙智能小车设计方案是什么?二、使用步骤1.准备硬件2.准备一个串口通信的代码3.修改源码三、运行与调试总结前言    daodanjishui物联网核心原创技术之最简单DIY基于STM32单片机的蓝牙智能小车设计方案。    市面上有各种开源STM3

    2022年10月10日
    4
  • 基于Python获取局部点云平面的上位机软件

    基于Python获取局部点云平面的上位机软件

    2020年11月8日
    204
  • FAT32文件系统结构详解[通俗易懂]

    FAT32文件系统结构详解[通俗易懂]1.SD卡中FAT32文件系统快速入门1.1.理论知识1.1.1.MBR(MainBootRecord)主引导记录,占446字节,为计算机启动后从可启动介质上首先装入内存并且执行的代码,通常用来解释分区结构1.1.2.DBR(DOSBootRecord)DOS引导记录,为操作系统进入文件系统以后可以访问的第一个扇区,通常用来解释文件系统,DBR是由硬盘的MBR装…

    2025年8月18日
    3

发表回复

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

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