java - 凭空安全

标签 java multithreading

Java Concurrency in Practice解释这个概念:

When a thread reads a variable without synchronization, it may see a stale value, but at least it sees a value that was actually placed there by some thread rather than some random value. This safety guarantee is called out-of-thin-air safety.



这种类型的安全性是否很弱,因为它可能包含陈旧的值(value)?

也许这个片段,at least it sees a value that was actually placed there by some thread than some random value , 之所以提到,是因为该书之前的主题是 JVM 对变量语句重新排序的可能性,引用 sharing variables without synchronization ?

示例:取决于重新排序: 42 或 0 可以打印出来。
public class NoVisibility {
    private static boolean ready;
    private static int number;

    private static class ReaderThread extends Thread {
        public void run() {
            while(!ready)  
                Thread.yield();
            System.out.println(number);
            }
        }

    public static void main(String[] args) {
        new ReaderThread().start();
        number = 42;
        ready = true;
    }
}

已编辑 - 删除了“请评论”的评论。

最佳答案

“凭空安全”确实是比例如安全性弱得多的保证。 “顺序一致性”,但在某种意义上可以称之为“强”。也就是说,如果您的系统提供 OOTA 安全,您可以对您的程序进行推理 比如果您的系统没有提供它要好。如果您使用的系统不提供 OOTA 安全性,那么您基本上就完蛋了。

Hans Boehm 和 Brian Demsky 最近写了一篇关于这个主题的论文,题目是“取缔鬼魂:避免无中生有的结果”(PDF available on ACM.org).他们给出了一些非常好的示例,说明非 OOTA 安全系统可能如何工作,以及此类系统中可能会出现哪些类型的错误。

基本思想是允许某些系统做投机执行 ,包括对内存(缓存)的推测存储,如果系统的推测结果不正确,可以在以后撤消。这在单线程系统中效果很好,但在多线程系统中,两个线程的推测可能会相互影响,从而创建 “失控的谣言工厂” : 处理器 A 认为 x=42,因为处理器 B 在那里推测性地存储了 42,但处理器 B 只存储了 x=42,因为处理器 A 告诉它 y=17...但处理器 A 只是基于 x=42 的假设进行推测!

void rivera() {                 void lemon() {
    if (x == 42) {                  if (y == 17) {
        y = 17;                         x = 42;
    }                               }
}                               }

“非 OOTA 安全”系统可能会重写这些方法,使其看起来像(使用伪 Python-Javascript 语法,抱歉)
void rivera() {
    assert(y not in cache);  // for the sake of argument
    cache.y = 17;  // for the sake of speed, speculatively report that y=17
    if (x not in cache) {
        cache.x = x;  // meanwhile, slowly fetch the real value of x
    }
    if (cache.x != 42) {
        delete cache.y;  // discard the earlier, speculative write
    }
    // and then later write cache.y back into the y in main memory
}

你可以看到如果 lemon() 会是个大问题信任 rivera()的推测性报告cache.y = 17反之亦然。两种方法都完成后,我们可能会出现 x=42 的情况。和 y=17即使他们都不是那样开始的!

我知道人们通常依赖time-travel paradox比喻来描述值 42 和 17 是如何“凭空”出现在主内存中的,但我认为有线新闻的比喻更准确。 ;)

关于java - 凭空安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21243858/

相关文章:

java - 多线程修改StringBuilder

ios - Objective-c 验证当前执行线程,以防万一,在正确的线程中重新执行该方法

java - WEB-INF 目录中的 JSF 文件,如何访问它们?

java - 我可以在创建 JPEG 时更改 Java 的 ImageWriter 使用的压缩算法吗?

Java EE WebListener 和线程

java - Collections.unmodifiableList(list) 是否需要锁?

c++ - Boost.Asio 异步 TCP 客户端和多线程

java - 编译时收到错误消息(Java Web 项目)

java - Tomcat 上下文初始化失败

java - 接口(interface)不明确继承的字段