这是最初的问题,但我的问题与它有一些不同。C++ 内存模型 - 此示例是否包含数据争用?
我的问题:
//CODE-1: initially, x == 0 and y == 0
if (x) y++; // pthread 1
if (y) x++; // pthread 2
Run Code Online (Sandbox Code Playgroud)
注意:上面的代码是用 C 编写的,而不是 C++(没有内存模型)。那么它是否包含数据竞争?
从我的角度来看:如果我们在顺序一致性内存模型中查看代码,则不存在数据竞争,因为 x 和 y 永远不会同时为非零。但是,我们永远不能假设顺序一致性内存模型,因此编译器重新排序可以进行尊重线程内正确性的转换,因为编译器不知道线程的存在......对吗?
所以代码可以改写为:
//CODE-2
y++; if (!x) y--;
x++; if (!y) x--;
Run Code Online (Sandbox Code Playgroud)
上面的转换没有违反顺序正确性,所以它是正确的。这不是编译器的错,对吧?所以我同意 CODE-1 包含数据竞争的观点。你呢?
我有一个额外的问题,带有内存模型的 C++11 可以解决这个数据竞争,因为编译器知道线程,所以他们会根据内存模型类型进行重新排序,对吧?
当今许多编程语言都具有happens-before关系和release+acquire同步操作。
其中一些编程语言:
\n\n我想知道是否release+acquire可以违反happens-before:
release+acquire和happens-beforeRelease/acquire建立happens-before不同线程之间的关系:换句话说,保证releasein之前的所有内容在afterThread 1中可见:Thread 2acquire
\\ Thread 1 / \n \\ -------- / \n \\ x = 1 / Everything \n \\ y …Run Code Online (Sandbox Code Playgroud) 语言规范中专门针对 Java 内存模型 (JMM) 的部分(链接)多次提到“执行跟踪”。
例如从一开始:
给定一个程序和该程序的执行跟踪,存储器模型描述该执行跟踪是否是该程序的合法执行。Java 编程语言内存模型的工作原理是检查执行跟踪中的每次读取,并根据特定规则检查该读取观察到的写入是否有效。
但我找不到这个术语的任何描述/定义。
那么,JMM 中的“执行跟踪”到底是什么?它到底由什么组成?
最受欢迎的是对语言规范文本中特定位置的引用。
我经常读到链表数据结构及其变体跳过列表在并行硬件中是缓存友好的.这是什么意思 ?有人可以用一种易于理解的方式解释.
编辑:上下文位于 此链接中.
我有以下代码
class VolatileCount {
volatile int count;
Object lock = new Object();
public void increment() {
synchronized (lock) {
count = count + 1;
}
System.out.print(" " + count);
}
}
Run Code Online (Sandbox Code Playgroud)
如果我increment()从多个线程调用相同的对象,我会得到以下输出(可能在您的机器上有所不同)
2 3 2 5 4 8 8 6 11 13 10 9 15 14 12 20 19
Run Code Online (Sandbox Code Playgroud)
看看我认为发生的重复数字似乎被破坏了,因为考虑前三个数字(2 3 2),如果线程看到3,则发生增量,并且因为变量是易变的,所以它的值应该是3或更多但是在任何线程中都不能为2.
但是,打印线似乎已在这里重新排序,重新排序该行是否正确?我在这里错过了什么?我运行JDK 7(Eclipse)
在《Effective Java》一书中:
// Broken! - How long would you expect this program to run?
public class StopThread {
private static boolean stopRequested;
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (!stopRequested)
i++;
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}
Run Code Online (Sandbox Code Playgroud)
背景线程不会在一秒后停止。因为JVM、HotSpot服务器VM中的提升、优化都是如此。
您可以在以下主题中查看这一点:
为什么 HotSpot 将使用提升来优化以下内容?。
优化过程是这样的:
if (!done)
while (true)
i++;
Run Code Online (Sandbox Code Playgroud)
有两种方法可以解决该问题。
private static volatile …Run Code Online (Sandbox Code Playgroud) 我尝试理解最终字段的语义.
让研究代码:
public class App {
final int[] data;
static App instance;
public App() {
this.data = new int[]{1, 0};
this.data[1] = 2;
}
public static void main(String[] args) {
new Thread(new Runnable() {
public void run() {
instance = new App();
}
}).start();
while (instance == null) {/*NOP*/}
System.out.println(Arrays.toString(instance.data));
}
}
Run Code Online (Sandbox Code Playgroud)
我有一些问题:
PS我不知道如何使标题正确,随时编辑.
如果我们更换,是否有可见性差异:
public App() {
this.data = new int[]{1, 0};
this.data[1] = 2;
}
Run Code Online (Sandbox Code Playgroud)
同
public App() {
int [] data …Run Code Online (Sandbox Code Playgroud) 我正在观看 java jpoint 会议的视频。
我对以下来自Alexey Shipilev报告的幻灯片有疑问:
对不起,幻灯片上的非英语。实际上作者说变量集是不可能的
r1 = 1 (Y)
r2 = 0 (x)
r3 = 1 (x)
r4 = 0 (Y)
Run Code Online (Sandbox Code Playgroud)
根据视频,他暗示显然是这样。
有人可以澄清为什么根据 JMM 设置这个值是不可能的吗?
聚苯乙烯
如果我理解 Alexey 符号是正确的,它会遵守以下代码:
public class SequentialConsistency {
static volatile int x;
static volatile int y;
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
x = 1;
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
y = 1;
}
}).start();
new …Run Code Online (Sandbox Code Playgroud) 我看了这个答案,并说明了如何:
在新的内存模型下,当线程A写入易失性变量V,并且线程B从V读取时,在写入V时对A可见的任何变量值现在都保证对B可见.
因此,举个例子:
public class Main {
static int value = -1;
static volatile boolean read;
public static void main(String[] args) {
Thread a = new Thread(() -> {
value = 1;
read = true;
});
Thread b = new Thread(() -> {
while (!read);
System.out.println("Value: " + value);
});
a.start();
b.start();
}
}
Run Code Online (Sandbox Code Playgroud)
value尽管value(仅read)的非波动性,是否保证线程b可以看到(从-1到1)的变化?
如果是这样,给定了一堆为了对另一个线程可见而进行的更改,是否有任何目的使得任何变量发生变化而不是最后一个变量?
java multithreading volatile java-memory-model memory-visibility
我认为Java规范中volatile的示例有些错误。
在8.3.1.4中。挥发性字段,它说
class Test {
static int i = 0, j = 0;
static void one() { i++; j++; }
static void two() {
System.out.println("i=" + i + " j=" + j);
}
}
Run Code Online (Sandbox Code Playgroud)
...然后方法二可能偶尔会为j打印一个大于i的值,因为该示例不包含同步,并且在第17.4节中解释的规则下,i和j的共享值可能会更新为订购。
我认为,即使这些更新是按顺序进行的,方法二仍可能看到j大于i,因为System.out.println("i=" + i + " j=" + j)它不是原子的,并且i在j之前被读取。
方法二是一样的
read i
read j
Run Code Online (Sandbox Code Playgroud)
所以有可能
read i
i++
j++
read j
Run Code Online (Sandbox Code Playgroud)
在这种情况下,方法二看到j的值大于i,但是更新不会乱序。
因此,乱序并不是看到j> i的唯一原因
应该是System.out.println("j=" + j + " i=" + i);吗?
这次故障是看到j> i的唯一原因
java ×9
volatile ×3
concurrency ×2
memory-model ×2
c ×1
c++ ×1
c++11 ×1
caching ×1
final ×1
jls ×1
jvm ×1
memory ×1
synchronized ×1
visibility ×1