如何确保通过匿名可运行对象传递给已经运行的线程的对象的可见性

时间:2014-01-10 04:49:39

标签: java thread-safety visibility runnable anonymous

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

但是,我无法理解如何确保从辅助线程通过匿名runnable查看对象,因为同一上下文中的两个线程不再访问该对象。

假设我有一个类似于下面的执行程序类,其他来自其他线程的对象(例如,线程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上实例化一个新对象并用它做一些事情,那么通过一个匿名的runnable将它发送给执行者,如下所示:

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中对对象的任何更改都可见?那个子元素的变化怎么样 - 铲子?

1 个答案:

答案 0 :(得分:0)

  1. 是的,你是对的。
  2. 使用volatileAtomic