简体   繁体   English

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

[英]java thread safe code + an atomic method question

I have a class Manager that is going to be accessed by multiple threads at the same time, I want to know if I did it the right way ? 我有一个可以同时被多个线程访问的类管理器,我想知道我是否做对了吗?
also I think I need RemoveFoo to be atomic, but I'm not sure 我也想我需要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
{}

You do not need synchronised methods as you are using a ConcurrentHashMap, however be aware that Foo foo = foos.Get(name) could return null as another thread could already have removed the entry from the map. 使用ConcurrentHashMap时不需要同步方法,但是请注意Foo foo = foos.Get(name)可能返回null,因为另一个线程可能已经从映射中删除了该条目。

Members can be declared as Map<String, Foo> foos , but must be initialsed as foos = new ConcurrentHashMap<String, Foo>; 成员可以声明为Map<String, Foo> foos ,但必须foos = new ConcurrentHashMap<String, Foo>;foos = new ConcurrentHashMap<String, Foo>;

RemoveFoo could be problematic. RemoveFoo可能有问题。 I suggest to use: 我建议使用:

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

instead. 代替。 This makes sure that the map doesn't change between get() and remove() . 这样可以确保在get()remove()之间映射不会改变。

In Foo , it's enough to synchronize on bars instead of the whole instance. Foo ,足以在bars而不是整个实例上进行同步。 But that's just a minor optimization. 但这只是次要的优化。

Declare RemoveFoo(String) as synchronized : 声明RemoveFoo(String)为已synchronized

public synchronized void RemoveFoo(String name) {
    …
}

Also, be advised of the following: 另外,请注意以下几点:

  • method names should be lower case, eg removeFoo instead of RemoveFoo . 方法名称应小写,例如removeFoo而不是RemoveFoo This is not C#. 这不是C#。 :) :)
  • Every method needs a return type: public removeFoo() is not a valid method declaration, it needs to be public void removeFoo() . 每个方法都需要一个返回类型: public removeFoo()不是有效的方法声明,它必须是public void removeFoo()

If you use a concurrentHashMap in Foo like 如果您在Foo中使用并发HashMap

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

maybe you can do away with the synchronization in Foo as well. 也许您也可以取消Foo中的同步。

I am not sure what you are going to do on Foo and Bar, but it looks like a pattern of deallocation. 我不确定您将在Foo和Bar上做什么,但是它看起来像是释放模式。

If they are not referenced by others, just call foos.Remove(name); 如果其他人未引用它们,则只需调用foos.Remove(name);。 and let GC engine handle the deallocation. 并让GC引擎处理释放。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM