提到锁,大家肯定想到的是sychronized关键字。是用它可以解决一切并发问题,但是,对于系统吞吐量要求更高的话,我们这提供几个小技巧。帮助大家减小锁颗粒度,提高并发能力。
初级技巧-乐观锁
乐观锁使用的场景是,读不会冲突,写会冲突。同时读的频率远大于写。
悲观锁的实现:
悲观的认为所有代码执行都会有并发问题,所以将所有代码块都用sychronized锁住
乐观锁的实现:
乐观的认为在读的时候不会产生冲突为题,在写时添加锁。所以解决的应用场景是读远大于写时的场景。
中级技巧-String.intern()
乐观锁不能很好的解决大量的写冲突的问题,但是很多场景下,锁只是针对某个用户或者某个订单。 比如一个用户先创建session,才能进行后面的操作,但是由于网络的问题,创建session的请求和后续请求几乎同时到达,而并行线程可能会先处理后面的请求。一般情况需要对用户sessionMap加锁,比如上面的乐观锁。在这样的场景下,可以将锁限定在用户本身上,即原来的
这个比较类似行锁和数据库表锁的概念。显然行锁的并发能力比表锁的高很多。
实用String.intern();是这种方式的具体实现。类String维护了一个字符串池。当调用intern方法时,如果池已经包含一个等于此String对象的字符串(该对象由equals(Object)方法确定),则返回池中的字符串。可见,当String 相同时,总返回同一个对象,因此就实现了对同一用户加锁。由于所的颗粒度局限于具体用户,使得系统获得最大程度的并发。
CopyOnWriteMap?
既然说到了“类似于数据库中的行锁的概念”,就不得不提一下MVCC,Java中CopyOnWrite类实现了MVCC。Copy On Write是这样一种机制。当我们读取共享数据的时候,直接读取,不需要同步。当我们修改数据的时候,我们就把当前数据Copy一份副本,然后在这个副本 上进行修改,完成之后,再用修改后的副本,替换掉原来的数据。这种方法就叫做Copy On Write。
但是,,,JDK并没有提供CopyOnWriteMap,为什么?下面有个很好的回答,那就是已经有了ConcurrentHashMap,为什么还需要CopyOnWriteMap?
高级技巧 - 类ConcurrentHashMap
String.inter()的缺陷是类 String 维护一个字符串池是放在JVM perm区的,如果用户数特别多,导致放入字符串池的String不可控,有可能导致OOM错误或者过多的Full GC。怎么样能控制锁的个数,同时减小粒度锁呢?直接使用Java ConcurrentHashMap?或者你想加入自己更精细的控制?那么可以借鉴ConcurrentHashMap的方式,将需要加锁的对象分为多个bucket,每个bucket加一个锁,伪代码如下:
到此这篇关于Java 高并发的三种实现案例详解的文章就介绍到这了,更多相关Java 高并发的三种实现内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!