JAVA 同步锁


需求: 同一个订单才加同步锁,不同订单可并行

synchronized

synchronized是Java中的关键字,是一种同步锁,是原生语法层面的互斥,需要jvm实现。它修饰的对象有以下几种:
  1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
  2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
  3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
  4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。

synchronized 作用当前对象

在这里插入图片描述
测试效果:
一)线程1 与 线程2 ,结果 线程1结束了线程2才开始。
在这里插入图片描述

synchronized 作用订单号条件

在这里插入图片描述
测试效果:
一)线程1 与 线程2 ,结果 线程1线程2可以同时开始。
在这里插入图片描述
二)线程1 与 线程1 ,结果 线程1与另一个线程1同时开始
synchronized 的锁不是比较字符串,而是对象,所以每次请求进来的orderId不是同一个对象。
在这里插入图片描述

synchronized 作用订单号字符串条件

把 synchronized 锁的 orderId 放在常量池中,那每次请求进来的就是同一个对象。
在这里插入图片描述
测试效果:
一)线程1 与 线程1 ,结果 线程1线程1锁住了。
在这里插入图片描述
二)线程1 与 线程2,结果 线程1与线程2同时开始。
在这里插入图片描述

ReentrantLock 加 ConcurrentHashMap

ReentrantLock它是JDK 1.5之后提供的API层面的互斥锁,需要lock()和unlock()方法配合try/finally语句块来完成

------------------------------------------------controller
@RestController
 public class OrderController{
 	@Autowired
 	SynchronizedByKey synchronizedByKey;

	@ResponseBody
	@RequestMapping("")
	pubilc Map<String,Object> process(@PathVariable("orderId")String orderId){
		SynchronizedByKey.exec(orderId,() ->{
			logger.debug("[{}] 开始",orderId);
			logger.debug("[{}] 结束",orderId);
		});
	}
}

------------------------------------------------SynchronizedByKey 
public class SynchronizedByKey {
	Map<String,ReentrantLock>  mutexCache = new ConcurrentHashMap<>;
	
	public void exec(String key,Runnable statement){
		ReentrantLock mutex4Key = null;
		ReentrantLock mutexInCache;
		do{
			if(mutex4Key != null){
				mutex4Key.unlock();
			}
			mutex4Key  = mutexCache.computeIfAbsent(key, k -> new ReentrantLock());
			mutex4Key.lock();
			/* lock()后再根据key去mutexCache取一把锁(mutexInCache),
				极端情况:
				1.我刚刚拿到了这把锁(mutexInCache),又从map里取的时候它为空了,说明我刚刚拿到的那么锁被remove掉了;
				2.我刚刚拿到了这把锁(mutexInCache),被新进来的线程(都是001)又创建了一把新锁覆盖了,
					所以mutex4Key 和 mutexInCache 不等; */
			mutexInCache = mutexCache.get(key);
		} while(mutexInCache == null || mutex4Key != mutexInCache);
		
		try{
			statement.run();
		} finally{
			if(mutex4Key.getQueueLength() == 0){
				mutexCache.remove(key);
			}
			mutex4Key.unlock();
		}
		
	}
}

学习视频链接

@Override
    public ResultMessage<Object> imgAndVideoHandler(TaskImgVideoParams taskImgVideoParams, String accessToken) {
        AuthUser authUser = UserContext.getAuthUser(cache, accessToken);
        //如果用户未登录,则无法上传图片
        if (authUser == null) {
            throw new ServiceException(ResultCode.USER_AUTHORITY_ERROR);
        }
        if (taskImgVideoParams.getFile().isEmpty() || taskImgVideoParams.getFile().getSize() <= 0) {
            return ResultUtil.error(ResultCode.LEADER_PHOTO_VIDEO_NULL_ERROR);
        }

        String descriptionId;
        List<PhotoAndVideo> photoVideoByGroupId = null;
        //String groupId = taskImgVideoParams.getGroupId().intern();
        synchronized (this) {
            photoVideoByGroupId = getPhotoVideoByGroupId(taskImgVideoParams.getGroupId());
            if (photoVideoByGroupId.size() < 1) {
                Description description = new Description(taskImgVideoParams.getContent(), taskImgVideoParams.getLeaderId(),
                        taskImgVideoParams.getTaskDay(), taskImgVideoParams.getReceiveTaskId());
                boolean saveDescription = descriptionService.save(description);
                if (!saveDescription) {
                    return ResultUtil.error(ResultCode.LEADER_SAVE_PHOTO_VIDEO_DESCRIPTION_ERROR);
                }
                descriptionId = description.getId();
            } else {
                descriptionId = photoVideoByGroupId.get(0).getDescriptionId();
            }

            String url = "";
            try {
                url = fileBuyerService.writeFile(taskImgVideoParams.getFile(), "F:\\IMAGES", "IMAGES");
            } catch (IOException e) {
                e.printStackTrace();
                fileBuyerService.deleteFile(url, "F:\\IMAGES");
                if (photoVideoByGroupId.size() > 1) {
                    for (PhotoAndVideo photoVideo : photoVideoByGroupId) {
                        fileBuyerService.deleteFile(photoVideo.getUrl(), "F:\\IMAGES");
                    }
                }
                deleteByGroupId(taskImgVideoParams.getGroupId());
                descriptionService.removeById(descriptionId);
                return ResultUtil.error(ResultCode.LEADER_SAVE_PHOTO_VIDEO_ERROR);
            }
            PhotoAndVideo photoAndVideo = new PhotoAndVideo(url, taskImgVideoParams.getOrder(), taskImgVideoParams.getGroupId(), descriptionId);
            boolean savePhotoAndVideo = this.save(photoAndVideo);
            if (!savePhotoAndVideo) {
                deleteByGroupId(taskImgVideoParams.getGroupId());
                descriptionService.removeById(descriptionId);
                return ResultUtil.error(ResultCode.LEADER_SAVE_PHOTO_VIDEO_ERROR);
            }
            return ResultUtil.success();
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值