Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 放松记忆顺序可以用来观察一个条件吗? std::原子b; 空f { //A区 ifb.loadstd::内存\u顺序\u松弛 { //B区 } //C区 } 空g { //B区 b、 storetrue,std::内存\u顺序\u释放; }_C++_Atomic_Memory Barriers_Memory Model_Stdatomic - Fatal编程技术网

C++ 放松记忆顺序可以用来观察一个条件吗? std::原子b; 空f { //A区 ifb.loadstd::内存\u顺序\u松弛 { //B区 } //C区 } 空g { //B区 b、 storetrue,std::内存\u顺序\u释放; }

C++ 放松记忆顺序可以用来观察一个条件吗? std::原子b; 空f { //A区 ifb.loadstd::内存\u顺序\u松弛 { //B区 } //C区 } 空g { //B区 b、 storetrue,std::内存\u顺序\u释放; },c++,atomic,memory-barriers,memory-model,stdatomic,C++,Atomic,Memory Barriers,Memory Model,Stdatomic,理论上,只有当原子负载返回真值时,才能执行块B, 但是,是否有可能在加载之前对块B的一部分进行重新排序?使用释放内存顺序存储可以保证块B上的所有操作都是可见的副作用,但如果加载是一个轻松的操作,这是否仍然适用?您应该关心的原则是访问您使用此互斥锁锁定的资源。如果没有acquire/release语义,您的线程可能看不到其他线程对该资源所做的更改。也就是说,您对该数据的读取和另一个线程对其的写入构成了一场没有获取/释放语义的数据竞赛 如果您只想访问原子值本身,就应该使用宽松的内存顺序,而不必考虑世

理论上,只有当原子负载返回真值时,才能执行块B,
但是,是否有可能在加载之前对块B的一部分进行重新排序?使用释放内存顺序存储可以保证块B上的所有操作都是可见的副作用,但如果加载是一个轻松的操作,这是否仍然适用?

您应该关心的原则是访问您使用此互斥锁锁定的资源。如果没有acquire/release语义,您的线程可能看不到其他线程对该资源所做的更改。也就是说,您对该数据的读取和另一个线程对其的写入构成了一场没有获取/释放语义的数据竞赛


如果您只想访问原子值本身,就应该使用宽松的内存顺序,而不必考虑世界上与该原子值相关的其他情况。

您应该关心的原则是访问使用此互斥锁锁定的资源。如果没有acquire/release语义,您的线程可能看不到其他线程对该资源所做的更改。也就是说,您对该数据的读取和另一个线程对其的写入构成了一场没有获取/释放语义的数据竞赛


如果您只想访问原子值本身,而不考虑世界上与该原子值相关的其他情况,则只应使用松弛内存顺序。

英特尔建议在尝试锁定之前进行松弛加载:

acquire\u lock使用acquire语义,因此松弛的负载不会在acquire\u lock之后重新排序


但是,请注意,它首先尝试无条件锁定,然后再使用松弛加载执行繁忙等待循环。

英特尔建议在尝试锁定之前执行松弛加载:

acquire\u lock使用acquire语义,因此松弛的负载不会在acquire\u lock之后重新排序

然而,请注意,它首先尝试无条件锁定,然后再使用松弛负载执行繁忙等待循环。

在您的示例中有两个块B。我说的是在真空f荷载函数中的那个

是否有可能在加载之前对块B的部分进行重新排序

对。编译器可以将负载从if体中吊出,并在b.load之前执行这些操作。如果块B和块C都读取相同的非原子变量,则可能发生这种情况

即使没有编译时重新排序,也有一些实际机制会创建这种重新排序:

具体而言,分支推测(即分支预测+无序推测执行)将允许CPU在B.load开始之前开始执行块B

您不能依赖因果关系或任何类型的推理,就像它必须知道b.load结果才能知道下一步执行什么一样

或者,若在块B中并没有任何存储,编译器可能会将if转换为无分支代码。那个么很明显,它可以使用块B和块C中的非原子加载或其他松弛或获取加载进行重新排序

记住,acq/rel是单向屏障

基于真正的编译器和CPU所能做的事情进行这样的推理,有助于证明某些东西是不安全的。但是要小心另一种方法:基于我知道的编译器的基于安全性的推理并不总是意味着在便携式ISO C++中安全。 有时,我所知道的编译器上的安全性或多或少是足够的,但很难将其与我所知道的编译器上的工作区分开来,因为未来的编译器版本或看似无关的源代码更改可能会破坏某些东西

因此,总是尝试用C++内存模型来解释内存排序,以及如何对你关心的ISA(例如,强排序的x86)进行高效编译。就像您可能看到的那样,relaxed允许编译时重新排序,这在您的示例中非常有用。

您的示例中有两个块B。我说的是在真空f荷载函数中的那个

是否有可能在加载之前对块B的部分进行重新排序

对。编译器可以将负载从if体中吊出,并在b.load之前执行这些操作。如果块B和块C都读取相同的非原子变量,则可能发生这种情况

即使没有编译时重新排序,也有一些实际机制会创建这种重新排序:

具体而言,分支推测(即分支预测+无序推测执行)将允许CPU在B.load开始之前开始执行块B

您不能依赖因果关系或任何类型的推理,就像它必须知道b.load结果才能知道下一步执行什么一样

或编译器c 若在块B中并没有任何存储,那个么若将if转换为无分支代码,则可能会执行ould。那个么很明显,它可以使用块B和块C中的非原子负载或其他松弛或获取负载进行重新排序

记住,acq/rel是单向屏障

基于真正的编译器和CPU所能做的事情进行这样的推理,有助于证明某些东西是不安全的。但是要小心另一种方法:基于我知道的编译器的基于安全性的推理并不总是意味着在便携式ISO C++中安全。 有时,我所知道的编译器上的安全性或多或少是足够的,但很难将其与我所知道的编译器上的工作区分开来,因为未来的编译器版本或看似无关的源代码更改可能会破坏某些东西



因此,总是尝试用C++内存模型来解释内存排序,以及如何对你关心的ISA(例如,强排序的x86)进行高效编译。正如您可能看到的那样,relaxed允许编译时重新排序,这在您的情况下非常有用。

AFAIK只有加载本身才保证是原子的。其余部分仍然可以重新排序,等等。我看不出文章的标题与正文有什么对应。@Evg抱歉,我不太擅长简要描述技术问题。你能提出一个更好的标题吗?嗯,你没有try\u锁和互斥锁。我猜你是在问,你是否可以用原子来模拟那些无锁的东西。在这种情况下,标题对应良好,如果有点不清楚。我已经删除了标题中令人困惑的提及互斥。如果你把它带回来,请添加一个关于Q对互斥体的适用性的部分。AFAIK只有负载本身保证是原子的。其余部分仍然可以重新排序,等等。我看不出文章的标题与正文有什么对应。@Evg抱歉,我不太擅长简要描述技术问题。你能提出一个更好的标题吗?嗯,你没有try\u锁和互斥锁。我猜你是在问,你是否可以用原子来模拟那些无锁的东西。在这种情况下,标题对应良好,如果有点不清楚。我已经删除了标题中令人困惑的提及互斥。如果你把它带回来,请添加一个关于你的Q对互斥体的适用性的部分。啊,这样你就可以执行一个轻松的操作,看看原子是否被写入,如果是的话,用acquire order再次加载,以防止之前重新排序?这非常有帮助,谢谢。啊,那么你可以执行一个轻松的操作,看看原子是否被写入,如果是的话,用获取顺序再次加载,以防止之前重新排序?这很有帮助,谢谢。@curiousguy:你能不能别再散布关于mo_的恐惧了?是的,各种编译时优化可以在源代码中的其他内容之后重新排序松弛的加载。一些理论上的运行时效应也是如此,比如没有实际CPU可以做的值预测,而且不太可能很快实现。mo_Released并不是从根本上不可靠的,如果你关心订购wrt,它只是不合适。除非重新排序受到附近围栏或acq/rel操作的限制,否则不得进行任何其他操作。发布存储确实会强制在存储之前发生一个松弛的负载。@PeterCordes:但这不是我要说的。无论块B做什么,如果这确实是某种形式的互斥,在Curiousguy更改它之前,它是OP的原始措辞,那么这意味着有其他线程访问了一些内存,原子获取是为了防止同时访问,通信写线程已完成,读线程可以读取值。如果只使用宽松的内存顺序,那么块B中的读取将导致与另一个线程的数据竞争。这就是互斥应该防止的。@curiousguy即使我不同意你关于放松原子的分析,我也不认为你一直提到的问题应该被删除。人们有权提出问题,即使这个问题挑战了标准,因此被许多人认为是有争议的。我不知道为什么它会被删除,或者是其他的,但是也许你可以让一个版主把它重新放回网上。@ LWMSI:我不能说明为什么它被删除了,但是它被关闭了,因为它是非常宽泛的,本质上是为了解释和证明C++内存模型而沸腾。在规范中,线程内存模型由5个页面组成,这不需要查看标准库中增加页面数的各种内容。这还不包括关于该规范的各种离奇和不准确的说法。总的来说,这个问题的措辞不像是寻找真相,更像是试图传播FUD;你什么时候停止殴打你的妻子的?这是个问题。@Nicolabolas我必须承认,我不记得这个问题的具体细节,但在我看来,好像有人在情绪反应中删除了它,我认为这是一个不好的理由。但我也同意,确实有一些案例
fy问题将被关闭和/或删除。@curiousguy:你能停止散布关于mo_的恐惧吗?是的,各种编译时优化可以在源代码中的其他内容之后重新排序松弛的加载。一些理论上的运行时效应也是如此,比如没有实际CPU可以做的值预测,而且不太可能很快实现。mo_Released并不是从根本上不可靠的,如果你关心订购wrt,它只是不合适。除非重新排序受到附近围栏或acq/rel操作的限制,否则不得进行任何其他操作。发布存储确实会强制在存储之前发生一个松弛的负载。@PeterCordes:但这不是我要说的。无论块B做什么,如果这确实是某种形式的互斥,在Curiousguy更改它之前,它是OP的原始措辞,那么这意味着有其他线程访问了一些内存,原子获取是为了防止同时访问,通信写线程已完成,读线程可以读取值。如果只使用宽松的内存顺序,那么块B中的读取将导致与另一个线程的数据竞争。这就是互斥应该防止的。@curiousguy即使我不同意你关于放松原子的分析,我也不认为你一直提到的问题应该被删除。人们有权提出问题,即使这个问题挑战了标准,因此被许多人认为是有争议的。我不知道为什么它会被删除,或者是其他的,但是也许你可以让一个版主把它重新放回网上。@ LWMSI:我不能说明为什么它被删除了,但是它被关闭了,因为它是非常宽泛的,本质上是为了解释和证明C++内存模型而沸腾。在规范中,线程内存模型由5个页面组成,这不需要查看标准库中增加页面数的各种内容。这还不包括关于该规范的各种离奇和不准确的说法。总的来说,这个问题的措辞不像是寻找真相,更像是试图传播FUD;你什么时候停止殴打你的妻子的?这是个问题。@Nicolabolas我必须承认,我不记得这个问题的具体细节,但在我看来,好像有人在情绪反应中删除了它,我认为这是一个不好的理由。但我同意,确实有一些案例证明问题是可以关闭和/或删除的。
ATTEMPT_AGAIN:
    if (!acquire_lock())
    {
        /* Spin on pause max_spin_count times before backing off to sleep */
        for(int j = 0; j < max_spin_count; ++j)
        {
            /* pause intrinsic */
            _mm_pause();
            if (read_volatile_lock()) // <--- relaxed load
            {
                if (acquire_lock())
                {
                    goto PROTECTED_CODE;
                }
            }
        }
        /* Pause loop didn't work, sleep now */
        Sleep(0);
        goto ATTEMPT_AGAIN;
    }
PROTECTED_CODE:
    get_work();
    release_lock();
    do_work();