• 不使用mutex设计模式解决并发访问cache


    上周同事做了一个代码的分享,分享了在code中解决并发请求访问cache的问题。

    使用了ConcurrentHashMap充当mutex锁,伪代码如下:

    public class XXX{
        private ConcurrentHashMap map = new ConcurrentHashMap();
        public Object get(key){
            Object o = cache.get(key);
            if(o==null){
                Object lock = new Object();
                /*关于ConcurrentHashMap 的 putIfAbsent方法 doc 是这样说的:
                * the previous value associated with the specified key,
                * or null if there was no mapping for the key
                */
                Object _lock = map.putIfAbsent(key, lock);
                if(_lock==null){//说明没有其他线程同时请求
                    o = db.get(key);
                    cache.put(key, o);
                    _lock.notifyAll();//唤醒其他等待的线程
                }else{
                    _lock.wait();//线程等待,被唤醒
                    o = cache.get(key);
                }
            }
            return o;
        }
    }

      不由的想到了之前看到的Timyang在blog中写的《Memcache mutex设计模式》http://timyang.net/programming/memcache-mutex/,另外还有孙立的一个跟帖文章http://www.cnblogs.com/sunli/archive/2010/07/27/cache_key_mutex.html今天拿出来又看了一下。基本上和同事的思路是一样的,只是用memcached完成的mutex锁

    if (memcache.get(key) == null) {
        // 3 min timeout to avoid mutex holder crash
        if (memcache.add(key_mutex, 3 * 60 * 1000) == true) {
            value = db.get(key);
            memcache.set(key, value);
            memcache.delete(key_mutex);
        } else {
            sleep(50);
            retry();
        }
    }

    Ps:这里顺便复习一下memcached set,replace,add方法

    * add      仅当存储空间中不存在键相同的数据时才保存
    * replace 仅当存储空间中存在键相同的数据时才保存
    * set      与add和replace不同,无论何时都保存,如果 key 存在就是替換 value

    然后想到了用Double Check 的方式应该也是一个不错的选择,并且代码看上去更简洁

    public Object get(key){
        Object o = cache.get(key);
        if(o==null){
            doGet(key);
        }
        return o;
    }
    
    public synchronized Object doGet(key){
        Object o = cache.get(key);
        if(o==null){
            o = db.get(key);
        }
        return o;
    }
  • 相关阅读:
    CPU die
    删除binlog的方法
    mysql中bigint、int、mediumint、smallint 和 tinyint的取值范围
    Javascript中的Keycode值列表
    php5.2转向 PHP 5.3 的 PHP 开发
    linux 下查看系统内存使用情况的方法
    Kyoto Cabinet(DBM) + Kyoto Tycoon(网络层)
    window 7 下一台cp 两个mysql 配置主从
    php 序列化(serialize)格式详解
    Linux下ntpdate时间同步
  • 原文地址:https://www.cnblogs.com/beanchoc/p/3209541.html
Copyright © 2020-2023  润新知