gpt4 book ai didi

Java - volatile 未按预期工作

转载 作者:行者123 更新时间:2023-12-01 21:37:28 24 4
gpt4 key购买 nike

我目前正在尝试研究并发性,特别是“ volatile ”关键字。

By declaring the counter variable volatile all writes to the counter variable will be written back to main memory immediately. Also, all reads of the counter variable will be read directly from main memory. Here is how the volatile declaration of the counter variable looks

When a thread writes to a volatile variable, then not just the volatile variable itself is written to main memory. Also all other variables changed by the thread before writing to the volatile variable are also flushed to main memory. When a thread reads a volatile variable it will also read all other variables from main memory which were flushed to main memory together with the volatile variable.

来源:tutorials.jenkov.com | Java Concurrency - Java Volatile Keyword

这让我得出结论/假设我对 volatile 变量所做的任何更改始终对所有线程可见。所以,我编写了一个代码来测试它。

<强> TestClass

package org.personal.test1;

class TestClass {
public static int w = 0;
public static int x = 0;
public static int y = 0;
public static volatile int z = 0;
private static final int ITERATIONS = 100000;


public static void sooPlus(int indents) {
for (int i = 0; i < TestClass.ITERATIONS; i++) {
TestClass.w++;
TestClass.x++;
TestClass.y++;
TestClass.z++;
}
}

public static void sooMinus(int indents) {
for (int i = 0; i < TestClass.ITERATIONS; i++) {
TestClass.w--;
TestClass.x--;
TestClass.y--;
TestClass.z--;
}
}


public static synchronized String getVariableValues () {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("(");
stringBuilder.append("w : "+TestClass.w+", ");
stringBuilder.append("x : "+TestClass.x+", ");
stringBuilder.append("y : "+TestClass.y+", ");
stringBuilder.append("z : "+TestClass.z+")");
return stringBuilder.toString();
}

}

<强> Main Class

package org.personal.test1;

/**
* <ol type="I">
* <li>
* <a href="http://tutorials.jenkov.com/java-concurrency/volatile.html">jenkov.com - Java Volatile Keyword</a>
* </li>
* </ol>
*/
public class Main {

public static void main(String[] args) {
Main.call1();
}

private static void call1() {
Main.test1();
}

private static void test1() {
Thread thread1 = new Thread("Thread1") {
@Override
public void run() {
TestClass.sooPlus(1);
}
};

Thread thread2 = new Thread("Thread2") {
@Override
public void run() {
TestClass.sooMinus(4);
}
};

thread1.start();
thread2.start();

try {
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}

try {
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}

System.out.println(TestClass.getVariableValues());

}
}

我得到的结果不是我所期望的。

我得到什么(各不相同)

(w : -2314, x : -1692, y : -1416, z : -1656)

我的期望

(w : 0, x : 0, y : 0, z : 0)

或者至少

(w : -2314, x : -1692, y : -1416, z : 0)

问题

  1. 我假设/得出的错误是什么导致了与预期不同的输出?
  2. 我的测试方法是否不正确?如果是的话我该如何解决?
  3. (可选)您有推荐的有关 Java 并发性的优秀教程吗?

注释

  • 我确实尝试阅读类似的问题,但我无法完全理解提问者试图做什么来理解他的问题。

最佳答案

volatile 关键字提供了弱形式的线程安全性。它保证可见性,但不保证原子性或互斥性

  • volatile 字段有可能不是线程安全的吗?线程安全。对非 volatile doublelong 值的写入不是原子的,但对 volatile doublelong 变量的写入是原子的.

  • 由所有 volatile 字段组成的类是否可能不是线程安全的?是的,如果对字段的写入导致无效的状态转换(由于缺乏同步)。

(optional) Are there any good tutorial on Java Concurrency that you recommend?

通常推荐作为该主题的权威论述的书是 Brian Goetz 所著的《Java Concurrency in Practice》。有点老了。

关于Java - volatile 未按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36814490/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com