根据我在互联网上读到的一些文献,类原子的变量,如AtomicInteger,AtomicLong,……只允许一个线程同时访问它们。但是当我尝试用AtomicBoolean进行测试时,有些地方出了问题。例如
public class TestAtomicBoolean {
public static void main(String[] args) {
final AtomicBoolean atomicBoolean = new AtomicBoolean(false);
new Thread("T1") {
@Override
public void run() {
while (true) {
System.out.println(Thread.currentThread().getName() + " is waiting for T3 set Atomic to true. Current is " + atomicBoolean.get());
if (atomicBoolean.compareAndSet(true, false)) {
System.out.println("Done. Atomic now is " + atomicBoolean.get());
break;
}
}
}
}.start();
new Thread("T2") {
@Override
public void run() {
while(true) {
System.out.println(Thread.currentThread().getName() + " " + atomicBoolean.get());
}
}
}.start();
new Thread("T3") {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " " + atomicBoolean.get());
System.out.println(Thread.currentThread().getName() + " is setting atomic to true");
atomicBoolean.set(true);
System.out.println(Thread.currentThread().getName() + " " + atomicBoolean.get());
}
}.start();
}
}输出
T1 is waiting for T3 set Atomic to true. Current is false
T1 is waiting for T3 set Atomic to true. Current is false
T3 is setting atomic to true
T2 false
T3 true (*)
T1 is waiting for T3 set Atomic to true. Current is false (*)
T2 true
Done. Atomic now is false
T2 false在第2行(*),尽管T3将AtomicBoolean设置为true,但在此之后,T1读取的值为false。那么,T1和T3同时访问AtomicBoolean?我不明白AtomicBoolean是如何工作的。
有人能帮我吗?
发布于 2016-03-24 05:37:13
AtomicBoolean绝对是原子的和线程安全的.
但是在您的示例中,您试图测试AtomicBoolean的原子性质,依赖于System.out.println打印日志的顺序,这是误导的。
因此,如果我们看一下System.out.println()代码:
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}我们将在上下文中看到使用上述println()方法的事件流。
短答案
线程T1打印->正在等待T3设置为true。电流是假的
线程T1打印->正在等待T3设置为true。电流是假的
线程T3打印-> T3正在将原子设置为true
线程T1 调用sysout打印->正在等待T3设置为true。Current是false (只是调用了sysout方法,但还没有锁定)
线程T3打印->printing of T3 true
线程T1 sysout完成并打印->正在等待T3设置为true。电流是假的
日志的顺序给人的印象是,T1没有读取atomicBoolean的当前值,而这是因为执行System.out.println时可能发生的线程交织。
详细序列
应用程序以false用于atomicBoolean的初始值开始
final AtomicBoolean atomicBoolean = new AtomicBoolean(false);输出的最初两个日志与预期的一样来自T1,它将atomicBoolean的值打印为false。现在,我们将忽略T2来简化,因为即使有两个线程,我们也可以看到流。
现在,T3开始执行,并将按照输出中的指示将atomicBoolean转换为true。
T3 is setting atomic to true在打印上面的行之后,T1就有机会执行。此时,atomicBoolean的值是false。所以JVM创建了字符串T1 is waiting for T3 set Atomic to true. Current is false和关于调用的内容,或者只是输入了System.out.println方法,但是还没有到达synchronized(this)语句,因此还没有在this上获得任何锁。
此时可能发生,T3已经开始继续执行,并将atomicBoolean转换为true,并使用System.out.println()打印行T3 true,即获取和释放锁(在this上)。
现在,T1从上次离开的位置(即System.out.println )恢复执行。但是请记住,它试图打印的字符串的值已经构建,其值为T1 is waiting for T3 set Atomic to true. Current is false。现在,T1打印这一行并继续。
有效地使用此流,日志将如您所观察到的那样。
T3 true
T1 is waiting for T3 set Atomic to true. Current is false图像表示
下面是w.r.t T1 & T3流程,并(尝试)捕捉上述讨论。----表示线程当前正在执行。空格表示它正在等待轮到它。
1(false) 1(false) 1(false)just invoked 1(false)completed
T1 ------------------- ------ ------------------
T3 ---------- ----------------
2(false) 3(true)
LEGEND:
1(false) - printing of T1 is waiting for T3 set Atomic to true. Current is false
2(false) - printing of T3 is setting atomic to true
3(true) - printing of T3 true发布于 2016-03-24 04:23:37
与其引用“一些文档”,不如尝试阅读https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html的官方文档。
考虑原子包中的类的一种快速而简单的方法是,每个方法(如get、set、compareAndSet )的行为就好像它是同步的(忘记了惰性和弱方法)。
https://stackoverflow.com/questions/36193183
复制相似问题