gpt4 book ai didi

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

转载 作者:qq735679552 更新时间:2022-09-28 22:32:09 25 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章java高并发锁的3种实现示例代码由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

初级技巧 - 乐观锁 。

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

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

java" id="highlighter_503618">
?
1
2
3
4
5
6
7
8
public Object get(Object key) {
   synchronized (map) {
    if (map.get(key) == null ) {
      // set some values
    }
     return map.get(key);
   }
}

乐观锁的实现:

?
1
2
3
4
5
6
7
8
9
10
11
12
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加锁,比如上面的乐观锁。在这种场景下,可以讲锁限定到用户本身上,即从原来的 。

?
1
2
3
4
5
6
7
lock.lock();
 
   int num=storage.get(key);
 
   storage.set(key,num+ 1 );
 
lock.unlock();

更改为:

?
1
2
3
4
5
6
7
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()总是返回同一个对象,因此就实现了对同一用户加锁。由于锁的粒度局限于具体用户,使系统获得了最大程度的并发.

?
1
2
3
4
5
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加一个锁,伪代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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高并发锁的3种实现示例代码的文章就讲到这里了,如果你想了解更多关于java高并发锁的3种实现示例代码的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com