java线程安全代码+原子方法问题

时间:2009-12-03 09:01:49

标签: java multithreading atomic

我有一个类管理器,它将同时由多个线程访问,我想知道我是否以正确的方式进行了操作?
另外我认为我需要RemoveFoo是原子的,但我不确定

public class Manager
{
    private ConcurrentHashMap<String, Foo> foos;
    //init in constructor

    public RemoveFoo(String name)
    {
        Foo foo = foos.Get(name);
        foo.RemoveAll();
        foos.Remove(name);
    }

    public AddFoo(Foo foo)
    {...}
}

public class Foo
{
    private Map<String,Bar> bars;
    //intialize it in constructor

    //same for RemoveBar
    public void AddBar(Bar bar)
    {
        synchronized(this)
        {
            bars.put(bar.id, bar);
        }
    }

    public void RemoveAll()
    {
        synchronized(this)
        {
            //some before removall logic for each one
            bars.remove(bar.id, bar);
        }
    }

}

public class Bar
{}

5 个答案:

答案 0 :(得分:4)

您使用ConcurrentHashMap时不需要同步方法,但请注意Foo foo = foos.Get(name)可能会返回null,因为另一个线程可能已经从地图中删除了该条目。

成员可以声明为Map<String, Foo> foos,但必须初始为foos = new ConcurrentHashMap<String, Foo>;

答案 1 :(得分:3)

RemoveFoo可能会有问题。我建议使用:

Foo foo = foos.remove (name);
if (foo != null) foo.removeAll();

代替。这可确保地图在get()remove()之间不会发生变化。

Foo中,只需在bars上进行同步,而不是整个实例。但这只是一个小小的优化。

答案 2 :(得分:1)

RemoveFoo(String)声明为synchronized

public synchronized void RemoveFoo(String name) {
    …
}

另外,请注意以下事项:

  • 方法名称应为小写,例如removeFoo代替RemoveFoo。这不是C#。 :)
  • 每个方法都需要一个返回类型:public removeFoo()不是有效的方法声明,它必须是public void removeFoo()

答案 3 :(得分:1)

如果你在Foo中使用concurrentHashMap

private Map<String,Bar> bars = new ConcurrentHashMap<String, Bar>();

也许你可以在Foo中取消同步。

答案 4 :(得分:1)

我不确定你要对Foo和Bar做什么,但它看起来像是一种解除分配的模式。

如果他们没有引用他们,只需调用foos.Remove(name);并让GC引擎处理释放。