本文介绍了getter/setter方法和类的单例模式中的Java细粒度同步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用synchronization java指令在类中实现细粒度的同步,即,我可以同步最少的代码.在代码之后,我会问你如何改进代码:

I'm trying to use the synchronization java directive to implement fine-grained synchronization in a class, i.e. synchronize the least amount of code I can.. I'll comment the code inline, to explain what I do and after the code I'll ask you how to improve the code:

public class MyClass {
    private static volatile MyClass singletonInstance = null;

    private HashMap<String, Integer> mHashMap = null;
    private String mStringA = null;
    private String mStringB = null;


     // Use double check technique to use synchronization only 
     // at the first getInstance() invocation
    public static MyClass getInstance() {
        if (singletonInstance == null) {
            synchronized (MyClass.class) {
                if (singletonInstance == null)
                    singletonInstance = new MyClass();
                    // Initialize class member variables
                    singletonInstance.mHashMap = new HashMap<String,Integer>();
                    singletonInstance.mStringA = new String();
                    singletonInstance.mStringB = new String();
            }

        }
        return singletonInstance;
    }

    // The following two methods manipulate the HashMap mHashMap
    // in a secure way since they lock the mHashMap instance which
    // is always the same and is unique
    public Integer getIntegerFromHashmap(String key) {
        synchronized (mHashMap) {
            return mHashMap.get(key);
        }
    }

    public void setIntegerIntoHashmap(String key, Integer value) {
        synchronized (mHashMap) {
            mHashMap.put(key, value);
        }
    }

    // With the two String members mStringA and mStringB the problem is 
    // that the instance of String pointed by the member is varied by the 
    // setter methods, so we can not lock in a fine grained way and we
    // must lock on the singletonInstance.
    public String getStringA() {
        synchronized (singletonInstance) {
            return mStringA;
        }
    }

    public String getStringB() {
        synchronized (singletonInstance) {
            return mStringB;
        }
    }

    public void setStringA(String newString) {
        synchronized (singletonInstance) {
            mStringA = newString;
        }
    }

    public void setStringB(String newString) {
        synchronized (singletonInstance) {
            mStringB = newString;
        }
    }
}

我对两个String成员变量的getter和setter方法不满意的是,锁定singletonInstance可以使线程尝试访问mStringB,直到操作mStringA的线程为止.释放它的锁.在这种情况下,您会怎么做?您是否会在MyClass中创建两个成员变量,例如private final Integer mStringALock = new Integer(0)private final Integer mStringBLock = new Integer(0),并分别在mStringAmStringB的getter和setter方法的同步块中使用它们?

What I don't like about the getter and setter methods of the two String member variables is that locking on singletonInstance can make a thread trying to access mStringB wait until a thread that is manipulating mStringA releases its lock. What will you do in this case? Would you create two member variables like private final Integer mStringALock = new Integer(0) and private final Integer mStringBLock = new Integer(0) in MyClass and use them in the synchronized block of the getter and setter methods of mStringA and mStringB, respectively?

如果您对如何改进上述代码以及对String成员变量进行细粒度同步的建议变体有一些想法,欢迎您:)

If you have some ideas about how to improve the above code and the proposed variation for fine-grained synchronization of the String member variables, you are welcome :)

推荐答案

更简单的解决方案通常更易于实现.我还将使用在2004年添加的并发库.

Often simpler solutions are easier to implement. I would also use the concurrent library adding in 2004.

这不需要显式锁,每个容器都是线程安全的.

This doesn't require explicit locks and each container is thread safe.

您可以使用AtomicReference,但在这种情况下,它不会给您带来任何不稳定的影响. (如kdgregory所指出的)在更复杂的情况下,您可以使用AtomicReference.

You can use AtomicReference but in this case it doesn't give you anything volatile doesn't give you already. (As kdgregory pointed out) You might use AtomicReference in more complex cases.

public enum MyClass {
    INSTANCE;

    private final Map<String, Integer> mHashMap = new ConcurrentHashMap<String, Integer>();
    private volatile String mStringA = null;
    private volatile String mStringB = null;


    // The following two methods manipulate the HashMap mHashMap
    // in a secure way
    public Integer getIntegerFromHashmap(String key) {
        return mHashMap.get(key);
    }

    public void setIntegerIntoHashmap(String key, Integer value) {
        mHashMap.put(key, value);
    }

    public String getStringA() {
        return mStringA;
    }

    public String getStringB() {
        return mStringB;
    }

    public void setStringA(String newString) {
        mStringA = newString;
    }

    public void setStringB(String newString) {
        mStringB = newString;
    }
}

这篇关于getter/setter方法和类的单例模式中的Java细粒度同步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-24 13:18