BOOST源码笔记(5) - 最小的代价实现同步-无锁编程,看boost中的interlocked_bit_test_and_set实现

boost并发编程boost::atomic boost并发编程 三个用于并发编程的组件: atomic,thread,asio(用于同步和异步io操作) 1. atomic,封装了不同计算机硬件的底层操作原语,提供了跨平台的原子操作功能,解决并发竞争读写变量的困扰。 包含头文件, atomic可以把对类型T的操作原子化,T的要求: 1.标量类型,(算数,枚举,指针) 2.只有平凡拷贝/转移构造、赋值和析构函数的类,并且 阅读详情

如题,如何用最小的代价来实现同步呢,即无锁编程(主要是使用原子操作替代锁来实现对共享资源的访问保护),

我们来看看下面的代码。

首先,我们需要是在这个函数内部对地址x中的值进行位测试并将其对应的位置位。  这里的关键是我们必须先读出*x的值,作位或运算之后,将得到的值对*x赋值。而在多线程环境中,在读出*x后也许有另外的线程对*x进行写操作,这样在给*x赋值的时候就会把对旧的值位或的结果赋给*x,造成错误。

 

这里boost是采用一个循环,将读出的值先保存,这样,读出后的值就为一个不变量,然后计算位或,当然也为不变量。接着用win32中的atom函数interlockedCompareExchange()来对比*x是否在被读出值后改变,如果没改变,则赋值;反之,则更新被保存的变量,再重复判断,直到第前面的情况发生。

 

也许有人会说,如果我这样写呢,                   

long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,*x|value,*x);

是不是就可以避免读和写不一致。错!你这样还是读了共享变量,而且是2次!2次读出的值都可能不一样,使得可能被位或地值都不一致。而且是在进入atom函数后才是同步代码,而读共享变量值得时候是在函数外部,还需要压栈,完全可能不同步。

 

inline bool interlocked_bit_test_and_set(long* x,long bit)
            {
                long const value=1<<bit;
                long old=*x;
                do
                {
                    long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old|value,old);
                    if(current==old)
                    {
                        break;
                    }
                    old=current;
                }
                while(true);
                return (old&value)!=0;
            }

 

以上的函数所用的方法保证了对一个共享值的读-针对读出的值作操作-将操作后的值写回,这3步能够保持同步。我可以类举出win32中interlockedExchangeAdd() <即i++>的实现方法:

 

inline void interlockedExchangeAdd(long* x)
            {
                long old=*x;
                do
                {
                    long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old + 1,old); //

比较并交换操作的作用是在一个原子操作内,先将目标值和老的值进行比较,如果相等就将新的值赋给目标变量。目的是为了防止将新的值赋给目标变量前,在读写操作之间目标变量遭到其他线程的修改。


                    if(current==old)
                    {
                        break;
                    }
                    old=current;
                }
                while(true);
            }

 

 

以上就是lock-free编程中的经典的CAS(compare and swap)的实现,除此外Lock-Free编程还有三大优点:

  • 线程中止免疫:杀掉系统中的任何线程都不会导致其它线程被延迟。
  • 优先级倒置免疫:所谓“优先级倒置”就是指一个低优先级线程持有了一个高优先级线程所需要的互斥体。这种微妙的冲突必须由OS内核来解决。而等待无关和锁无关算法则对此免疫。
  • 死锁免疫:因为没有使用锁,所以也就不存在死锁的可能。但是乐观的并发,可能会导致活锁。

虽然Lock-Free编程非常困难,但是它通常可以带来比基于锁编程更高的吞吐量。所以Lock-Free编程是大有前途的技术。它在线程中止、优先级倒置以及信号安全等方面都有着良好的表现。

 

但是CAS会出现ABA问题,这就不在我们的讨论范围内了。转个ABA的解决:

 

即定义额外的标识之类得方法来区别第一次A和第二次的A(不重用A),使得CAS能够察觉变化。

 

 

BLDC方波控制双闭环Simulink仿真模型 无刷直流电机方波控制双闭环Simulink仿真模型搭建详细教程,包括速度PI环、电流PI环、换向逻辑和受控电压源,仿真结果良好。 阅读详情

相关推荐

Vmware虚拟机一打开就蓝屏解决方法

Vmware虚拟机一打开就蓝屏解决方法 问题: 一打开Vmware虚拟机就蓝屏,如下图所示: 解决方法1: 启用和关闭windows功能(对话框)——>虚拟机平台(选项打对勾,默认没勾选)——>确定后重启——>再进应该就好了。 解决方法2: ①.查看电脑中的Hyper-V服务是否关闭 1.打开控制面板-程序-程序和功能 2.双击启用或关闭Windows功能 3.把Hyper-V前面的勾去掉 如果后期发下没有反应,或者电脑本身Hyper-V的服务没有打开,可以先打开在关闭,试

m0_55901666的博客 26万+

明明白白自旋锁

标 题: 明明白白自旋锁 作 者: achillis 时 间: 2008-10-12,13:39:46 链 接:http://bbs.pediy.com/showthread.php?t=74502 自某日看了iceboy和MJ0011关于多处理器同步的一些讨论,才发现原来我对自旋锁的理解也有一定错误,还好现在明白了~~为了加深理解,就深入分析了一下自旋锁的实现,一篇小小的自旋锁分析文

kingswb的博客 1192

1. Klipper从安装到运行

本文记录Klipper固件从安装,配置到运行的详细过程

weixin_42098934的博客 1万+

boost学习与应用笔记之一:Boost.Atomic

Presenting Boost.Atomic Boost.Atomic is a library that provides atomic data types and operations on these data types,  as well as memory ordering constraints required for coordinating multiple thr

北雨南萍 3211

SPEI计算避坑指南:gma中Distribution和FitMethod参数怎么选?

本文深入探讨了在SPEI计算中如何科学选择gma库中的Distribution和FitMethod参数,帮助研究者避开常见陷阱。详细分析了LogLogistic、Gamma和Pearson3三种分布的适用场景,以及LMoment与MLE拟合方法的优缺点,为气象干旱研究提供实用指南。

weixin_30308101的博客 250

科研绘图实战:用Adobe Illustrator高效排版期刊论文图片

本文详细介绍了使用Adobe Illustrator高效排版科研论文图片的完整工作流。针对期刊投稿常见的图片格式问题,文章重点讲解了矢量图与位图的预处理、AI中的精准对齐与分布技巧、文字样式统一管理以及最终输出TIFF/PDF等符合出版要求的格式。掌握这套方法能确保图片满足高分辨率、规范字体和精确尺寸等期刊硬性标准,显著提升投稿效率。

tomato的博客 1430

bittest & bittestandset

// bittest.cpp// processor: x86, IPF, x64#include <iostream>#include <stdio.h>#include <intrin.h>//for _bittest() & _bittestandset()typedefunsignedcharbyte;//取32位整形数组的第i(i从0开...

weixin_30563917的博客 295

8台 × 8卡 910B NPU之顶尖大模型选型分析

本文对比了2026年主流大语言模型在昇腾910B NPU集群上的部署方案。重点评估了GLM5、MiniMax M2.5、Kimi K2.5、DeepSeek V3.2和Qwen 3.5旗舰版等候选模型,从部署需求(显存占用)、能力表现(基准测试、多模态支持)和NPU生态适配度三个维度进行分析。结果显示DeepSeek V3.2综合表现最优:支持BF16/W8A8/INT4量化,在4TB显存环境下可实现2000+ TPS,首token延迟<100ms,且具备官方NPU支持。备选方案Qwen 3.5旗舰版

FeelTouch Labs 755

test_bit、set_bit和clear_bit

//将addr的第nr(nr为0-31)位置值置为1; //nr大于31时,把高27的值做为当前地址的偏移,低5位的值为要置为1的位数 extern __inline__ int set_bit(int nr,int * addr) { int mask, retval; addr += nr >> 5; //nr大于31时,把高27的值做为当前地址的偏移, mask = 1 << (nr &amp...

Android 系统开发 1456

告别密码!用VScode+SSH一键连接树莓派,再也不用每次输密码了

本文详细介绍了如何通过VScode和SSH密钥实现树莓派的免密连接,告别繁琐的密码输入。从开发环境准备、SSH密钥生成与配置,到VScode远程连接优化和常见问题排查,提供了一套完整的解决方案,帮助开发者提升工作效率。

weixin_28831341的博客 172

【OpenFOAM】-olaFlow-算例4- irreg45degTank

不规则波浪模拟

ou_no的博客 2117

不允许重载函数“_interlockedbittestandreset”的第二个 C 链

编译时遇到的错误及处理方法 不允许重载函数“_interlockedbittestandreset”的第二个 C 链  将vs include file 删除 __MACHINEI(unsigned char _interlockedbittestandset(long volatile *a, long b)) __MACHINEI(unsigned char _interlockedb

TonyAnny专栏 4235

PCL 快速均匀下采样

快速均匀下采样 是一种点云降采样技术,通过设置采样步长来实现等距降采样,从而减少点的数量。用户可以通过指定步长,选择每隔一定数量的点采样一个点,这样可以在保持点云几何特性的同时,显著减少点的数量。

纵马踏花向自由 870

关于bit操作(bit_set test_bit)

    今天发现一个奇怪的现象,用linux内核的bitops.h里面的bit_set和test_bit居然没有不用汇编的代码快。记录下来,备忘。    下面是可执行程序,THUIRDB暂时没有bitops里面的实现,改用我自己写的实现了。当然bitops里的实现,nr可以很大,而我的代码nr只能是0-63之间的一个数,对THUIRDB的应用来说,足够了。#include "std

pennyliang的专栏 1万+

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

test_and_set_bit

Man page of test_and_set_bit(int nr, volatile void *addr)这样描述它的功能: "Set a bit and return its old value"  nr -- Bit to set  addr -- Address to count from 注意:nr是需要设置的“哪一位”,而不是将ad

helloworlddm的博客 3077

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

unsigned char _interlockedbittestandset(long volatile *a, long b)问题

因为某种原因,使用了 MSVC的编译器, 但是没有使用 visual studio IDE, 这时候, 如果还使用 旧的SDK package, 这时候在同时 Include intrin.h 和  WinNT.h 的时候, 就会出现这个错误: __MACHINEI(unsigned char _interlockedbittestandset(long volatile *a, long

一亩半分地 2169

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

_InterlockedAnd _InterlockedOr等原子级安全运算

http://msdn.microsoft.com/en-us/library/windows/desktop/ff471407(v=vs.85).aspx 内部与-安全操作 _InterlockedAnd  _InterlockedOr 在 VS2010 中,在x86  x64编译模式下 ,InterlockedAnd 与_InterlockedAnd 的使用问题

浴血重生-学习空间 2918

_bittest & _bittestandset

C 中的unsigned 类型默认为unsigned int类型。unsigned char为8bit都使用,没有符号位。char < unsigned char < int < unsigned int_bittest, _bittest64 在vs2005以后支持,返回值为unsigned char,如果要得到0或1的值需要进行强制类型转换。检查地址a中,第b位的值是0还是...

weixin_30376509的博客 435

位原子操作

一、理论:1.并发 并发的概念是:多个执行单元同时、并行被执行。 Linux系统是多任务的,很多任务会同时执行。 假如有三个执行单元ABC,共享了内存资源。 执行单元A对Buffer写1000个“a”; 执行单元B对Buffer写1000个“b”; 执行单元C从buffer中读取数据。 如果按照A写→C读→B写→C读,当然没有问题。 但是如果A写→B写→C读,执行单元C就出问题了。 当然比这个复杂...

danwuxie的博客 1040

c++11 std::atomic

reference: c++11 std::atomic https://www.jianshu.com/p/b7a2b36f43d9 使用原子的变量,++ 和 -- 的次数相同,最终为0; 没有使用原则的变量,++ 和 -- 的次数不相同,最终不为0; c++新特性之std::atomic https://blog.youkuaiyun.com/delongwang520/article/details/79604329 ...

Oliver King 的小窝 621

boost的多线程实现机理

对boost的多线程感觉挺好奇的,所以就追踪了以下。 设置在 下面,为了调用windows api,boost是这么做的 # include namespace boost { namespace detail { namespace w

关注3d图形技术,移动互联网 1709

并发学习-【转】深入理解并发之CompareAndSet(CAS)

程老师原文地址:http://flychao88.iteye.com/blog/2269438 原文如下: 一、CAS简介 CAS:Compare and Swap, 翻译成比较并交换。 java.util.concurrent包中借助CAS实现了区别于synchronouse同步锁的一种乐观锁,使用这些类在多核CPU的机器上会有比较好的性能. CAS有3个操作数,内存值V,旧的预期...

bohu83的博客 1万+

7.3 实现顺序死锁代码

简单顺序死锁的条件 1、两个线程1,2 2、两个资源a,b 3、两个线程先获取不同的资源(使用Thread.sleep) demo public class TestDeadLock { static class CustomerA extends Thread{ Object a; Object b; public CustomerA(Object a, Object b) { this.a = a; ...

一点光辉的博客 173

Java里的CompareAndSet(CAS)

Atomic 从JDK5开始, java.util.concurrent包里提供了很多面向并发编程的类. 使用这些类在多核CPU的机器上会有比较好的性能. 主要原因是这些类里面大多使用(失败-重试方式的)乐观锁而不是synchronized方式的悲观锁. 今天有时间跟踪了一下AtomicInteger的incrementAndGet的实现. 本人对并发编程也不是特别了解, 在这里就是做

fangchengimz的博客 344
上一篇: BOOST源码笔记(4) - thread_move_t概念
下一篇: BOOST源码笔记(6) - 无安全保证的随意转换~~~force_cast
daeees
博客等级 码龄19年 6粉丝 51原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值