2014-03-05 74 views
-2

线程安全我有一类是这样的:与Java静态内部类字段

public class Outer { 

    public static final TaskUpdater TASK_UPDATER = new TaskUpdater() { 

     public void doSomething(Task task) { 
      //uses and modifies task and some other logic 
     } 
    }; 

    public void taskRelatedMethod() { 
     //some logic 
     TASK_UPDATER.doSomething(new Task()); 
     //some other logic 
    } 
} 

我注意到在多线程环境中运行这个时候一些奇怪的行为,我不能在本地繁殖,我怀疑这是一个线程问题。通过在TASK_UPDATER上调用doSomething,Outer的两个实例可能以某种方式干扰对方吗?每个将传递任务的差异实例到doSomething方法中。

+1

您能否详细说明您观察到的奇怪行为? – Rainbolt

+1

鉴于'doSomething()'不同步,当然,两个线程可以同时执行'doSomething()'。它能引起“干扰”吗?我们怎么能看到这个类的一行代码? –

+1

每个线程都在处理它自己的'Task'实例?在'Outer'中是否有任何字段被修改? – Gray

回答

1

Outer的两个实例是否可能通过在TASK_UPDATER上调用doSomething而以某种方式干扰彼此?

答案是“视情况而定”。任何时候你有多个线程共享相同的对象实例,你可能会遇到并发问题。在你的情况下,你有多个实例Outer共享相同的staticTaskUpdater实例。这本身不是问题,但如果TaskUpdater有任何字段,它们将由线程共享。如果线程以任何方式对这些字段进行了任何更改,那么数据同步需要发生,并且可能会阻止关键代码段。如果TaskUpdater只有读取和操作Task的说法,这似乎是每个Outer实例,那就没有问题了。

例如,你可以有一个任务更新,如:。

public static final TaskUpdater TASK_UPDATER = new TaskUpdater() { 
    public void doSomething(Task task) { 
     int total = 0; 
     for (Job job : task.getJobs() { 
      total += job.getSize(); 
     } 
     task.setTotalSize(total); 
    } 
}; 

在这种情况下,任务只改变Task例如在通过它可以使用局部变量不会有问题,因为这些都是在堆栈,现在在线程之间共享。这是线程安全的。

但是考虑此更新:

public static final TaskUpdater TASK_UPDATER = new TaskUpdater() { 
    private long total = 0; 
    public void doSomething(Task task) { 
     for (Job job : task.getJobs() { 
      // race condition and memory synchronization issues here 
      total += job.getSize(); 
     } 
    } 
    public long getTotal() { 
     return total; 
    } 
}; 

在这种情况下,两个线程都将在碎片TaskUpdater更新同一total领域。这不是线程安全的,因为你的竞争条件是+=(因为它是3个操作:get,plus,set)以及内存同步问题。一个线程可能有total这是5,它递增至6缓存的版本,但另一个线程已经增加的total其缓存的版本,以10

当线程份额公共字段你需要保护这些业务而发愁关于互斥访问和内存发布的同步。在这种情况下,使total成为AtomicLong将是有序的。

private AtomicLong total = new AtomicLong(0); 
     ... 
      total.addAndGet(job.getSize()); 

AtomicLong包装了一个volatile long所以内存被适当地发布到所有线程,它有代码,不会原子测试/设置操作从而消除了竞争条件。