【问题标题】:How to ensure visibility of objects passed to an already running thread through an anonymous runnable object如何确保通过匿名可运行对象传递给已运行线程的对象的可见性
【发布时间】:2014-01-10 13:18:10
【问题描述】:

我一直在阅读有关 Java 中的并发性的内容,并且我了解如何使用同步来确保通过相同类型的路径访问对象时的互斥访问和保证可见性,例如两个线程都访问存储在相同数据结构中的对象。

但是,我无法弄清楚如何通过匿名可运行文件确保从辅助线程中看到对象的可见性,因为在同一上下文中的两个线程不再访问该对象。

假设我有一个如下所示的执行器类,其中来自其他线程(例如线程 1)的对象可以调用 execute(),并发送一个新任务以由执行器线程(线程 2)执行。

public class BasicExecutor extends Thread {

private final Object monitor = new Object();
private final ConcurrentLinkedQueue<Runnable> tasks = new ConcurrentLinkedQueue();
private boolean running = false;

public void execute(Runnable task) {
    tasks.add(task);

    synchronized (monitor) {
        if(!running) {
            monitor.notify();
        }
    }
}

public void run() {
    try {
        while(!Thread.interrupted()) {
            while(tasks.isEmpty()) {
                synchronized (monitor) {
                    running = false;
                    monitor.wait();
                    running = true;
                }
            }

            tasks.remove().run();
        }
    } catch (InterruptedException e) {
        System.out.println("Executor was interrupted");
    }
}
}

假设这个执行器自程序启动以来一直在运行,但可以等待(),直到收到要运行的新任务的通知。

如果我要在线程 1 上实例化一个新对象并用它做一些事情,然后通过匿名可运行将它发送给执行器,如下所示:

final Person p = new Person("Jim");
p.setName("Rob");
p.setItem(new Shovel(ShovelType.SILVER));

executor.execute(new Runnable() {
    public void run() {
        // read some information from p
        // do some stuff with that information
    }
});

我假设线程 2 在执行时不能保证对 Person 对象的更改是可见的,因为线程 2 很久以前就开始运行了,所以在创建线程时没有发生之前的行为。

首先,我的假设是否正确?其次,如何确保线程 1 中对象的任何更改对线程 2 可见?那么它的子元素 - 铲子的变化呢?

【问题讨论】:

    标签: java thread-safety visibility runnable anonymous


    【解决方案1】:
    1. 是的,你是对的。
    2. 使用volatileAtomic

    【讨论】:

    • 所以我应该首先在 Runnable 中将 Person 'p' 分配给 volatile Person pInRunnable = p 然后使用它?这会刷新对象的状态——即成员变量——还是只是它在内存中的地址?
    • 不,你也应该让成员变量变得易变。阅读 volatile 关键字:docs.oracle.com/javase/tutorial/essential/concurrency/…
    • 我想我在这里可能很愚蠢,但是如果我无权访问类实现怎么办?有没有办法将其包裹起来以使其安全?
    • 然后将变量设为 volatile,并使用同步块或方法包装所有突变。
    猜你喜欢
    • 2013-08-07
    • 2012-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-03
    • 1970-01-01
    • 2011-08-16
    • 1970-01-01
    相关资源
    最近更新 更多