本文介绍使用java synchronized同步锁来实现对相同userId进行加锁

众所周知synchronized只能锁对象地址,而对于如下加锁是完全没有用的

public void test(Long userId) {

synchronized (userId) {//除了-127-128外其他的值都锁不住

// ...

}

}

原因就在于±127之外的都是new除来的Long(见源码Long.valueOf),地址值当然不一样了。

既然synchronized需要同一个对象,那我们将同一对象缓存下来不就得了。

private HashMapmMap = new HashMap<>();

public Long getLock(Long userId) {

if (!mMap.containsKey(userId)) {

mMap.put(userId, userId);

}

return mMap.get(userId);

}

思路是对的,但:getLock本身就会有并发问题;每个需要锁的接口都得new一个全局的HashMap;当10000个用户调用了100个接口总计要保存1000000条userId在内存里,服务器运行时间越长积累越多。

于是改成了如下方式,代码虽长了一点,但效率几乎没有下降:

/**

* 由于synchronized只能锁对象的地址,所有像Long为1000的用户id是锁不住的

* 此类来解决这个问题

* synchronized (UserLockUtils.getLock("test" + userId)) {}

* 因为是全局的入参当然是"接口名+userId"最好了

*/

public class UserLockUtils {

private static HashMapmMapId = new HashMap<>(), mMapIdCache = new HashMap<>();

/**

* 缓存切换的开始时间,等待{@link #mCacheDeleteTime}时间后将清空切换数据

*/

private static long mCacheCreatTime;

/**

* 最大缓存数(当超出这一数值时,会自动清空),缓存切换等待时间

*/

private static int mMaxCache = 1000, mCacheDeleteTime = 10000;

public static synchronized String getLock(String oldId) {

String returnSt;

if (mMapId.size() < mMaxCache) {//数据比较少,普通的返回锁

if (!mMapId.containsKey(oldId)) {

mMapId.put(oldId, oldId);

}

returnSt = mMapId.get(oldId);

} else {//累加的残留数据太多,切换至缓存

//缓存开始时间

long nowMills = System.currentTimeMillis();

if (mMapIdCache.size() == 0) {

mCacheCreatTime = nowMills;

}

if (!mMapIdCache.containsKey(oldId)) {

mMapIdCache.put(oldId, mMapId.getOrDefault(oldId, oldId));

}

returnSt = mMapIdCache.get(oldId);

//等待mCacheChangeTime时间后清除原始数据

if (nowMills - mCacheCreatTime > mCacheDeleteTime) {

mMapId.clear();

//原始和缓存对调即可实现切换

HashMapchange = mMapId;

mMapId = mMapIdCache;

mMapIdCache = change;

}

}

return returnSt;

}

}

举例:登录接口,我们只需要传“接口名+userId”就可以对登录接口的userId加锁了。

public void login(Long userId) {

synchronized (UserLockUtils.getLock("login" + userId)) {

// ...

}

}

尽量不要直接传userId哦,如果所有接口都直接传userId估计就锁死了。

java id 锁_java 多线程synchronized同步锁锁住相同用户Id相关推荐

  1. java 多线程 串行 加锁_java多线程 synchronized 与lock锁 实现线程安全

    如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运行结果和单线程运行的结果是一样 的,而且其他的变量的值也和预期的是一样的,就是线程安全的. 通过卖火车票的例子 火车站要卖票,我们 ...

  2. java中什么是释放已经持有的锁_java多线程什么时候释放锁

    由于等待一个锁定线程只有在获得这把锁之后,才能恢复运行,所以让持有锁的线程在不需要锁的时候及时释放锁是很重要的.在以下情况下,持有锁的线程会释放锁: 1.当前线程的同步方法.代码块执行结束的时候释放 ...

  3. java 线程的可重入锁_java 多线程-可重入锁

    可重入锁:锁可以连续使用 计数器+判断进入的线程是不是已经锁定的线程,如果是那就不用等待,直接使用 public class my { public static void main(String[] ...

  4. java static 可见性_Java多线程 synchronized与可见性的关系以及可见性问题总结

    作者:七里香的编程之路 出自:OSCHINA 原文:my.oschina.net/u/4098550/blog/4548274 能保证可见性的措施 除了volatile 可以让变量保证可见性外.hap ...

  5. java 同步锁_Java多线程:synchronized同步锁的使用和实现原理

    作用和用法 在多线程对共享资源进行并发访问方面,JDK提供了synchronized关键字来进行线程同步,实现多线程并发访问的线程安全.synchronized的作用主要体现在三个方面:(1)确保线程 ...

  6. java中多线程模拟(多生产,多消费,Lock实现同步锁,替代synchronized同步代码块)...

    import java.util.concurrent.locks.*; class DuckMsg{int size;//烤鸭的大小String id;//烤鸭的厂家和标号 DuckMsg(){}D ...

  7. java线程钥匙_Java多线程并发编程/锁的理解

    一.前言 最近项目遇到多线程并发的情景(并发抢单&恢复库存并行),代码在正常情况下运行没有什么问题,在高并发压测下会出现:库存超发/总库存与sku库存对不上等各种问题. 在运用了 限流/加锁等 ...

  8. java线程池 锁_java多线程——锁

    这是多线程系列第四篇,其他请关注以下: 如果你看过前面几篇关于线程的文字,会对线程的实现原理了然于胸,有了理论的支持会对实践有更好的指导,那么本篇会偏重于线程的实践,对线程的几种应用做个简要的介绍. ...

  9. java线程释放_Java多线程出现异常会自动释放锁

    Java多线程出现异常会自动释放锁 package com.wkcto.intrinsiclock; /** * 同步过程中线程出现异常, 会自动释放锁对象 * * Author: 老崔 */ pub ...

  10. java线程 锁_Java多线程(二) 多线程的锁机制

    当两条线程同时访问一个类的时候,可能会带来一些问题.并发线程重入可能会带来内存泄漏.程序不可控等等.不管是线程间的通讯还是线程共享数据都需要使用Java的锁机制控制并发代码产生的问题.本篇总结主要著名 ...

最新文章

  1. 通过小代码体验程序中BSS段和DATA段的差异
  2. cool venn diagram
  3. Python自动化运维——文件与目录差异对比
  4. 绘制方法太单一!?这三个宝藏在线学习资源推荐给你~~
  5. timerfd API使用总结
  6. 【算法系列之二】反波兰式
  7. kubectl apply -f_广州车展捷豹路虎参展阵容 全新F-PACE 路虎卫士90
  8. HDU 6188 Duizi and Shunzi
  9. 《ANSYS 14.0超级学习手册》一2.5 本章小结
  10. bzoj3172:[Tjoi2013]单词
  11. 资源—稀疏编码(sparse coding)
  12. Jq-模拟最大化最小化关闭
  13. CSS:border的属性
  14. conv、deconv、fractional-strided conv
  15. find:paths must precede expression问题及解决
  16. Adaptation---多屏幕多分辨率的支持和一些概念
  17. 炼数成金数据分析课程---13、回归分析
  18. 随机森林实例:利用基于CART算法的随机森林(Random Forest)树分类方法对于红酒质量进行预测
  19. stamen的程序员之路
  20. mysql永久事务隔离级别_MySQL的事务隔离级别

热门文章

  1. Windows Live SkyDrive 介绍之图片存储:摄影师在线图片展示的新选择
  2. mysql standby_数据库的 standby模式
  3. markdown语法中的空格_markdown基本语法
  4. 北京中国科学院计算机专业怎么样,中国科学院北京计算技术研究所计算机技术怎么样...
  5. 面向对象之魔术方法_call
  6. 计算机网络课后习题概略
  7. java线程池正确使用姿势
  8. MongoDB三分钟插入100万数据
  9. 获取微信小程序二维码后返回一堆乱码
  10. QML 语法(Syntax)