【发布时间】: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