防止并发处理

20 篇文章 0 订阅

一. 缓存方式

以下是同个用户同时提交多个问题时的防并发处理

<span style="font-size:18px;">String simultaneouslyKey = "_key_simultaneously_"+loginAccount.getAccountId();
	Object obj = cacheClient.get(simultaneouslyKey);
	if (obj == null) {
		cacheClient.set(simultaneouslyKey, 1, new Date(System.currentTimeMillis() + 5000));
	} else {
		if(1 == (Integer)obj){
			json.put("ret", -1);
			json.put("msg", "您提交太频繁,请稍后提交");
			out.println(json.toString());
			return ;
		}
	}</span>

缓存方式在分布式环境下依然会出现并发的问题,下面介绍同步锁的方式,在分布式环境下同样有效

二. 同步锁方式

以下是同步锁的两个工具类:

<span style="font-size:18px;">public class McSyncUtils {

	/**
	 * 使用mc的并发CAS模式执行一段在分布式环境中需要同步的代码
	 * @param mcc
	 * @param mutexKey  同步锁的key
	 * @param event  同步处理事件
	 * @param mustExecSuccess  是否每个线程都必须等待执行success()方法,如果为false则表示第一次获取失败之后再也不等待继续执行了
	 * @throws InterruptedException
	 * void
	 * @author
	 * @update date 
	 */
    public static void execSyncCode(MemCachedClient mcc, String mutexKey, 
            SyncEvent event, boolean mustExecSuccess) throws InterruptedException{
        String currentValue = System.currentTimeMillis() + "";
        
        // 添加互斥锁,最长锁10秒钟
        if(mcc.add(mutexKey, currentValue, new java.util.Date(10 * 1000))){
        	String val = mcc.get(mutexKey).toString();
        	
        	if(currentValue.equals(val)){
	            if(event.syncCondition()){
	                event.success();
	            } else {
	                event.failure();
	            }
	            // 取消互斥锁
	            mcc.delete(mutexKey);	            
	            return;
        	}
        }
        
        // 该互斥锁已经被其他线程占用
        if(mustExecSuccess){
            // 等待获取锁资源
            Thread.sleep(50);
            // 重复执行
            execSyncCode(mcc, mutexKey, event, mustExecSuccess);
        } else {
            event.failure();
        }
    }
      
}</span>

<span style="font-size:18px;">/**
 * 
 * 同步处理事件,获得执行机会后执行sucess()方法,获取失败则执行failure()方法
 * @author 
 * @create date 
 */
public interface SyncEvent {
    /**
     * 执行同步业务代码的条件,满足该条件的时候才会进行获取锁执行success()中的代码
     */
    boolean syncCondition();

    /**
     * 获取到同步锁之后执行的事件
     */
    void success();

    /***
     * 获取同步锁失败或者没进行获取同步锁的时候执行的事件
     */
    void failure();
}</span>

案例:

<span style="font-size:18px;">   try {
    	    final MemCachedClient mcc = env.getBean("mcc", MemCachedClient.class);
            final String key = "exchangeGift2_" + giftId + "_" + accountId + "_" + mag;
            final String mutexKey = "exchangeGift2_" + giftId + "_" + accountId + "_" + mag + "_mutexkey";
	    McSyncUtils.execSyncCode(mcc, mutexKey, new SyncEvent(){
		@Override
		public boolean syncCondition(){
		// 如果该投票对应的key不存在则获取锁进行执行
	          return mcc.get(key) == null;
		}
		@Override
		public void success(){
		  mcc.set(key, "1", new java.util.Date(2 * 1000L));//2秒时间内对一个用户只能领取一次
		}
			    
	        @Override
		public void failure(){
		  throw new CoinException(111, "请稍后再来申请");
		}
			    
	     }, false);
         } catch (InterruptedException e1) {
	    throw new CoinException(111, "请稍后再来申请");
     }</span>




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值