java高并发锁的3种实现示例代码

作者:正在长大的毛毛虫 时间:2022-05-23 16:45:47 

初级技巧 - 乐观锁

乐观锁适合这样的场景:读不会冲突,写会冲突。同时读的频率远大于写。

以下面的代码为例,悲观锁的实现:


public Object get(Object key) {
 synchronized(map) {
  if(map.get(key) == null) {
    // set some values
  }
   return map.get(key);
 }
}

乐观锁的实现:


public Object get(Object key) {
 Object val = null;
 if((val = map.get(key) == null) {
   // 当map取值为null时再加锁判断
   synchronized(map) {
     if(val = map.get(key) == null) {
       // set some value to map...
     }
   }
 }
 return map.get(key);
}

中级技巧 - String.intern()

乐观锁不能很好解决大量写冲突问题,但是如果很多场景下,锁实际上只是针对某个用户或者某个订单。比如一个用户必须先创建session,才能进行后面的操作。但是由于网络原因,创建用户session的请求和后续请求几乎同时达到,而并行线程可能会先处理后续请求。一般情况,需要对用户sessionMap加锁,比如上面的乐观锁。在这种场景下,可以讲锁限定到用户本身上,即从原来的


lock.lock();

int num=storage.get(key);

storage.set(key,num+1);

lock.unlock();

更改为:


lock.lock(key);

int num=storage.get(key);

storage.set(key,num+1);

lock.unlock(key);

这个比较类似于数据库表锁和行锁的概念,显然行锁的并发能力比表锁高很多。

使用String.inter()是这种思路的一种具体实现。类 String 维护一个字符串池。 当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。可见,当String相同时,String.intern()总是返回同一个对象,因此就实现了对同一用户加锁。由于锁的粒度局限于具体用户,使系统获得了最大程度的并发。


public void doSomeThing(String uid) {
 synchronized(uid.intern()) {
   // ...
 }
}

CopyOnWriteMap?

既然说到了“类似于数据库中的行锁的概念”,就不得不提一下MVCC,Java中CopyOnWrite类实现了MVCC。Copy On Write是这样一种机制。当我们读取共享数据的时候,直接读取,不需要同步。当我们修改数据的时候,我们就把当前数据Copy一份副本,然后在这个副本 上进行修改,完成之后,再用修改后的副本,替换掉原来的数据。这种方法就叫做Copy On Write。

但是,,,JDK并没有提供CopyOnWriteMap,为什么?下面有个很好的回答,那就是已经有了ConcurrentHashMap,为什么还需要CopyOnWriteMap?

Fredrik Bromee 写道

I guess this depends on your use case, but why would you need a CopyOnWriteMap when you already have a ConcurrentHashMap?

For a plain lookup table with many readers and only one or few updates it is a good fit.

Compared to a copy on write collection:

Read concurrency:

Equal to a copy on write collection. Several readers can retrieve elements from the map concurrently in a lock-free fashion.

Write concurrency:

Better concurrency than the copy on write collections that basically serialize updates (one update at a time). Using a concurrent hash map you have a good chance of doing several updates concurrently. If your hash keys are evenly distributed.

If you do want to have the effect of a copy on write map, you can always initialize a ConcurrentHashMap with a concurrency level of 1.

高级技巧 - 类ConcurrentHashMap

String.inter()的缺陷是类 String 维护一个字符串池是放在JVM perm区的,如果用户数特别多,导致放入字符串池的String不可控,有可能导致OOM错误或者过多的Full GC。怎么样能控制锁的个数,同时减小粒度锁呢?直接使用Java ConcurrentHashMap?或者你想加入自己更精细的控制?那么可以借鉴ConcurrentHashMap的方式,将需要加锁的对象分为多个bucket,每个bucket加一个锁,伪代码如下:


Map locks = new Map();
List lockKeys = new List();
for(int number : 1 - 10000) {
 Object lockKey = new Object();
 lockKeys.add(lockKey);
 locks.put(lockKey, new Object());
}  
public void doSomeThing(String uid) {
 Object lockKey = lockKeys.get(uid.hash() % lockKeys.size());
 Object lock = locks.get(lockKey);
 synchronized(lock) {
  // do something
 }
}

来源:https://my.oschina.net/u/3101476/blog/1517905?utm_source=tuicool&utm_medium=referral

标签:java,高并发锁
0
投稿

猜你喜欢

  • SpringBoot项目的配置文件中设置server.port不生效问题

    2022-11-13 06:01:26
  • Docker搭建前端Java的开发环境详解

    2023-05-21 04:23:25
  • Mybatis如何传入多个参数的实现代码

    2022-02-26 02:52:24
  • java中javamail收发邮件实现方法

    2022-12-15 02:03:03
  • 使用WebSocket实现即时通讯(一个群聊的聊天室)

    2023-11-29 03:00:46
  • Java 数组高频考点分析讲解

    2021-09-01 13:14:36
  • 浅谈java的接口和C++虚类的相同和不同之处

    2023-08-05 12:01:51
  • JavaWeb项目Servlet无法访问问题解决

    2022-10-10 03:33:52
  • 使用Spring自定义实现IOC和依赖注入(注解方式)

    2023-09-16 04:42:35
  • java web实现邮箱激活与忘记密码

    2023-11-18 09:35:26
  • SpringBoot工程打包与运行的实现详解

    2023-11-10 23:51:28
  • SpringBoot使用validation-api实现对枚举类参数校验的方法

    2021-09-22 19:21:32
  • Java编程实现获取当前代码行行号的方法示例

    2021-06-28 06:51:14
  • Java并发之嵌套管程锁死详解

    2023-01-13 10:55:01
  • 19款Javascript富文本网页编辑器

    2021-12-08 23:48:45
  • JavaWeb使用POI操作Excel文件实例

    2022-06-12 18:19:30
  • java实现zip,gzip,7z,zlib格式的压缩打包

    2023-08-13 08:56:59
  • spring boot RestTemplate 发送get请求的踩坑及解决

    2022-01-19 16:08:09
  • Spring Boot 集成MyBatis 教程详解

    2021-10-12 04:49:21
  • Java实现简易Web服务器

    2023-11-17 09:10:11
  • asp之家 软件编程 m.aspxhome.com