在JLS的第17章中,它引入了一个概念:发生在一致之前.
如果对于A中的所有读取r,其中W(r)是r看到的写入动作,那么一组动作A发生 - 在一致之前,不是hb(r,W(r))或那里的情况在A中存在写w,使得wv = rv和hb(W(r),w)和hb(w,r)"
在我的理解中,它等于以下几个词:...,既不是......也不是......
所以我的前两个问题是:
它还给出了一个例子:17.4.5-1
Thread 1 Thread 2
B = 1; A = 2; 
r2 = A; r1 = B; 
在第一个执行顺序中:
1: B = 1;
3: A = 2;
2: r2 = A;  // sees initial write of 0
4: r1 = B;  // sees initial write of 0
订单本身已经告诉我们两个线程交替执行,所以我的第三个问题是:左数是什么意思?
在我的理解中,r2和r1的原因可以看出0的初始写入是A和B都不是volatile字段.所以我的第四个问题是:我的理解是否正确?
在第二个执行顺序中:
1: r2 = A;  // sees write of A = 2
3: r1 = B;  // sees …任何通常遵循的标准(ISO C或C++,或任何POSIX/SUS规范)是否有任何保证,由多个线程访问的变量(可能标记为volatile)(未被互斥锁保护)将最终保持一致如果分配给?
要提供一个特定示例,请考虑共享变量v的两个线程,初始值为零.
线程1:v = 1
线程2:while(v == 0)yield();
线程2是否保证最终终止?或者它可以想象永远旋转,因为缓存一致性从未启动并使得赋值在线程2的缓存中可见?
我知道C和C++标准(在C++ 0x之前)完全没有关于线程或并发的说法.但我很好奇,如果C++ 0x内存模型,或pthreads,或其他任何东西,保证这一点.(显然这确实可以在Windows上运行32位x86;我想知道它是否可以依赖于某些东西,或者它是否恰好在那里工作).
我有两个问题:
我想知道C++ 11和C11的标准是否会共享相同的内存模型规格.我读到这是事实,事实上C11是"继承"C++ 11内存模型(无论历史原因是后者发生在一起还是在同一时间/同一个人,尽管我认为Boehm,他是一个主要是C++人,有很多话要说.),但我想确保让某人更有知识.
我的下一个问题是:GCC会不会实现这种内存模型?我没有看到这方面的路线图,并想知道是否有人有"独家新闻".
我刚刚看过Herb Sutter的演讲:C++和2012年之后:Herb Sutter - 原子<>武器,2 of 2
他在std :: shared_ptr析构函数的实现中显示了错误:
if( control_block_ptr->refs.fetch_sub(1, memory_order_relaxed ) == 0 )
    delete control_block_ptr; // B
他说,由于memory_order_relaxed,删除可以放在fetch_sub之前.
在1:25:18 - 释放不保持在B线下面,它应该在哪里
怎么可能?在关系之前发生 - 之前/顺序 - 因为它们都在单线程中.我可能错了,但fetch_sub和delete之间也存在一个依赖关系.
如果他是对的,哪些ISO项目支持?
考虑以下伪代码:
expected = null;
if (variable == expected)
{
    atomic_compare_exchange_strong(
        &variable, expected, desired(), memory_order_acq_rel, memory_order_acq);
}
return variable;
观察执行检查时没有 "获取"语义variable == expected.
在我看来desired,总共至少会调用一次,每个线程最多调用一次.
此外,如果desired永远不会返回null,那么此代码将永远不会返回null.
现在,我有三个问题:
以上一定是真的吗?也就是说,即使在每次读取都没有围栏的情况下,我们是否真的可以对共享变量进行有序读取?
是否可以在C++中实现它?如果是这样,怎么样?如果没有,为什么?
(希望有一个理由,而不仅仅是"因为标准这样说".)
如果(2)的答案是肯定的,那么是否也可以在C++中实现它而不需要variable == expected执行原子读取variable?
基本上,我的目标是了解一旦代码被每个线程至少执行一次,是否有可能以与非共享变量相同的性能执行共享变量的延迟初始化?
(这有点像"语言 - 律师"问题.所以这意味着问题不在于这是一个好的还是有用的想法,而在于技术上是否可以正确地做到这一点.)
C++内存模型具有宽松的原子性,它不会对内存操作进行任何排序保证.除了我在这里找到的C中的邮箱示例:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1525.htm
基于本文中的激励示例:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2153.pdf
我很好奇这种同步机制的其他用例.
我有一个关于Java内存模型的问题.给出以下示例:
action 1
action 2
synchronized(monitorObject) { //acquire
    action 3
} //release
action 4
acquire并且release可以是任何与边缘同步(锁定,解锁,启动线程,连接线程,检测线程中断,易失性写入,易失性读取等)
它是保证action 3不能被移动之前的获取和不能被移动后的释放?
而且是保证action 2不能被移动后的获取(无论是发布之前,也没有之后),并且action 4不能移动之前的版本(无论是acquire之前也不之后)?
那么与编译器的重新排序操作同步 - 边缘" 双向障碍 "?
编辑1 我担心这一点,因为如果同步 - 边缘不是双向重新排序障碍,编译器可以通过将锁获取移动到其他人来简单地创建死锁.
或者是双向重新排序障碍甚至不需要防止这种情况,因为锁定获取不能被推送到其他人,因为这会改变同步顺序?
编辑2 操作1,2,3和4是JMM定义的" 线程间操作 " .
编辑3 这是一个示例,显示重新排序如何导致死锁:
x和y是共享变量,syncA和syncB可以由任何其他线程获取.但是使用以下代码,可能没有死锁.
/* 1 */  synchronized(syncA) {
/* 2 */      x = 1;
/* 3 */  }
/* 4 */  y = 0;
/* 5 …java multithreading memory-model compiler-optimization java-memory-model
我正在努力处理 C11 标准的第 5.1.2.4 节,特别是发布/获取的语义。我注意到https://preshing.com/20120913/acquire-and-release-semantics/(以及其他)指出:
... 释放语义防止写入释放的内存重新排序与程序顺序之前的任何读取或写入操作。
因此,对于以下情况:
typedef struct test_struct
{
  _Atomic(bool) ready ;
  int  v1 ;
  int  v2 ;
} test_struct_t ;
extern void
test_init(test_struct_t* ts, int v1, int v2)
{
  ts->v1 = v1 ;
  ts->v2 = v2 ;
  atomic_store_explicit(&ts->ready, false, memory_order_release) ;
}
extern int
test_thread_1(test_struct_t* ts, int v2)
{
  int v1 ;
  while (atomic_load_explicit(&ts->ready, memory_order_acquire)) ;
  ts->v2 = v2 ;       // expect read to happen before store/release 
  v1     = ts->v1 ;   // expect write …我正在阅读n3485中定义的C++内存模型,它讨论了发布/获取语义,根据我的理解,以及本博客中给出的定义:
收购语义是可以只适用于该操作的属性读取共享内存,无论是读-修改-写操作或普通负载.然后该操作被认为是读取.获取语义可防止读取采集的内存重新排序,并按程序顺序执行任何读取或写入操作.
发布语义是一种属性,它只能应用于写入共享内存的操作,无论它们是读取 - 修改 - 写入操作还是普通存储.然后将该操作视为写入释放.释放语义通过程序顺序中的任何读取或写入操作来防止写入释放的内存重新排序.
将阻止在当前读/写完成之前或之后重新排序读/写.第一个(获取)将确保当前正在执行的读取不会在其之后的任何读/写重新排序,后者(发布)将确保当前写入未使用之前的读/写操作重新排序它.
现在可以说std::mutex::lock它将获得语义并且std::mutex::unlock本质上具有发布语义吗?
在标准中,我可以在部分下找到它
30.4.1.2互斥体类型[thread.mutex.requirements.mutex]
11同步:
unlock()对同一对象的先前操作应与(1.10)此操作同步.
从我理解的同步并没有在标准中明确定义,但它似乎是在关系看两个不同线程之间评估的两个语句之前发生的类型,但是,根据我对获取/释放语义的理解,这有更多与记忆重新排序有关. 同步也可以称为发布/获取语义?
那么发布/获取语义是否不仅适用于加载/存储操作的重新排序以及操作的线程内交错?
在关于内存模型的标准部分中,它主要讨论了两个线程交错的有序关系.这可以解释这是否也适用于内存排序.
任何人都可以澄清一下吗?
正当我以为我已经掌握了原子知识时,我看到了另一篇文章。这是GCC wiki总体摘要下的摘录:
\n -Thread 1-       -Thread 2-                   -Thread 3-\n y.store (20);    if (x.load() == 10) {        if (y.load() == 10)\n x.store (10);      assert (y.load() == 20)      assert (x.load() == 10)\n                    y.store (10)\n                  }\n\n\n释放/获取模式只需要所涉及的两个线程同步。这意味着同步值与其他线程不可交换。线程 2 中的断言仍然必须为 true,因为线程 1 和 2 与 x.load() 同步。线程 3 不参与此同步,因此当线程 2 和 3 使用 y.load() 同步时,线程 3 的断言可能会失败。线程 1 和 3 之间没有同步,因此不能为“x”假设任何值。
\n
文章说线程 2 中的断言不会失败,但线程 3 中的断言可能会失败。
\n我觉得这很令人惊讶。这是我的推理链,线程 3 断言不会失败\xe2\x80\x94也许有人可以告诉我哪里错了。
\ny …