<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    上善若水
    In general the OO style is to use a lot of little objects with a lot of little methods that give us a lot of plug points for overriding and variation. To do is to be -Nietzsche, To bei is to do -Kant, Do be do be do -Sinatra
    posts - 146,comments - 147,trackbacks - 0

    前言

    在《ReferenceCountSet無鎖實現》中,詳細介紹了如何在一個進程中實現一個無鎖版本的ReferenceCountSet(或者說是在自己的代碼里沒有鎖),但是最近遇到一個問題,如果是在分布式的環境中呢?如何實現這個引用計數?這個問題如果從頭開始寫,會是一個比較復雜的問題,在實際中,我們可以使用ZooKeeper設置時的version機制來實現,即CAS(Compare-And-Set)。這是一個本人在實際項目中遇到的一個問題,但是會更簡單一些,因為在我們的項目中,我們使用GemFire,即已經有一個現成的分布式Map了(在Gemfire中叫做Region),所以問題簡化成如果如何使用一個分布式Map實現引用計數?

    實現

    如果對ConcurrentMap接口比較熟悉的話,這個其實是一個比較簡單的問題。在ConcurrentMap中最主要的就是引入幾個CAS相關的操作:
    public interface ConcurrentMap<K, V> extends Map<K, V> {
        V putIfAbsent(K key, V value);
        boolean remove(Object key, Object value);
        boolean replace(K key, V oldValue, V newValue);
        V replace(K key, V value);
    }
    在《ReferenceCountSet無鎖實現》中我們只需要使用putIfAbsent就可以了,剩下的實現可以交給AtomicInteger提供的CAS來實現,因為它是在同一個進程中,但是如果在分布式的環境中就不能使用這個AtomicInteger,這個時候應該怎么辦呢?其實這個時候我們就可以求助于replace方法了。replace方法的注釋中這樣描述:
        /**
         * Replaces the entry for a key only if currently mapped to a given value.
         * This is equivalent to
         * <pre>
         *   if (map.containsKey(key) &amp;&amp; map.get(key).equals(oldValue)) {
         *       map.put(key, newValue);
         *       return true;
         *   } else return false;</pre>
         * except that the action is performed atomically.
         *
         * 
    @param key key with which the specified value is associated
         * 
    @param oldValue value expected to be associated with the specified key
         * 
    @param newValue value to be associated with the specified key
         * 
    @return <tt>true</tt> if the value was replaced
         * 
    @throws UnsupportedOperationException if the <tt>put</tt> operation
         *         is not supported by this map
         * 
    @throws ClassCastException if the class of a specified key or value
         *         prevents it from being stored in this map
         * 
    @throws NullPointerException if a specified key or value is null,
         *         and this map does not permit null keys or values
         * 
    @throws IllegalArgumentException if some property of a specified key
         *         or value prevents it from being stored in this map
         
    */
        boolean replace(K key, V oldValue, V newValue);

    在ConcurrentMap的value中我們只需要給Integer,然后用replace去不斷的嘗試,即自己實現一個CAS:
    private int incrementRefCount(Object key) {
        do {
            Integer curCount = distributedMap.get(key);
            if (curCount == null) {
                curCount = distributedMap.putIfAbsent(key, new Integer(1));
                if (curCount == null) {
                    return 1;
                }
            }
            
            Integer newCount = new Integer(curCount.intValue() + 1);
            if (distributedMap.replace(key, curCount, newCount)) {
                return newCount;
            }
        } while (true);
    }

    主要邏輯就是這樣了,其實比較簡單,只是之前沒有遇到過這個問題,所以感覺可以記錄下來。或許什么時候補充一下ZooKeeper版本的實現。
    posted on 2015-04-20 20:30 DLevin 閱讀(5491) 評論(0)  編輯  收藏 所屬分類: Core Java
    主站蜘蛛池模板: 亚洲精品无码av片| 亚洲av中文无码乱人伦在线观看| 欧洲乱码伦视频免费国产| 亚洲成aⅴ人片久青草影院| 国产午夜亚洲精品不卡免下载| 成人免费无码精品国产电影| 美女免费视频一区二区| 亚洲精品无码久久毛片| 两个人看的www免费视频中文| 亚洲国产另类久久久精品小说| a级毛片免费全部播放无码| 亚洲日本一区二区| 免费99精品国产自在现线| 久久亚洲精品国产精品婷婷| 日韩免费三级电影| 一个人看www免费高清字幕| 亚洲Av无码精品色午夜| 4399好看日本在线电影免费| 亚洲国产aⅴ成人精品无吗| 免费一级特黄特色大片在线| 黄色网址免费在线观看| 亚洲网站在线观看| 免费av欧美国产在钱| 免费中文字幕视频| 久久久亚洲精品无码| 在线免费观看色片| 一级特级aaaa毛片免费观看| 亚洲国产精品久久久久| 免费无码看av的网站| 国产免费MV大全视频网站| 亚洲无人区视频大全| 国产成人精品免费视频大全五级 | 成人免费在线视频| 久香草视频在线观看免费| 亚洲国产精品高清久久久| 中字幕视频在线永久在线观看免费| 黄色大片免费网站| 亚洲欧洲尹人香蕉综合| 国产精品V亚洲精品V日韩精品| 亚洲免费视频观看| 毛片基地看看成人免费|