java并发编程之4——Java锁分解锁分段技术

转载自 java并发编程之4——Java锁分解锁分段技术

 

并发编程的所有问题,最后都转换成了,“有状态bean”的状态的同步与互斥修改问题。而最后提出的解决“有状态bean”的同步与互斥修改问题的方案是为所有修改这个状态的方法都加上锁,这样也就可以保证他们在修改bean的状态的时候是顺序进行的。但是这样整个过程的瓶颈也就是被加锁的这段代码。由此就产生了很多对程序加锁的优化思想,从整体上来看,可以分为两个部分:对单个锁的算法的优化。和对锁粒度的细分。

单个锁的优化

      自旋锁:非自旋锁在未获取锁的情况会被阻塞,之后再唤醒尝试获得锁。而JDK的阻塞和唤醒是基于操作系统实现的,会有系统资源的开销。自旋锁就是线程不停地循环尝试获得锁,而不会将自己阻塞,这样不会浪费系统的资源开销,但是会浪费CPU的资源。所有现在的JDK都的是先自旋等待,如果自旋等待一段时间之后还没有获取到锁,就会将当前线程阻塞。
      锁消除:当JVM分析代码发现某个方法只被单个线程安全访问,而且这个方法是同步方法,那么JVM就会去掉这个方法的锁。
单个锁优化的瓶颈
      对单个锁优化的效果就像提高单个CPU的处理能力一样,最终会由于各个方面的限制而达到一个平衡点,到达这个点之后优化单个锁的对高并发下面锁的优化效果越来越低。所以将一个锁进行粒度细分带来的效果会很明显,如果一个锁保护的代码块被拆分成两个锁来保护,那么程序的效率就大约能够提高到2倍,这个比单个锁的优化带来的效果要明显很多。常见的 锁粒度细分技术有:锁分解和锁分段

锁粒度细分

      锁的粒度细分主要有:锁分解和锁分段两种方式。他们的核心都是降低锁竞争发生的可能性。

锁分解

      锁分解的实现方式主要有两种:

缩小锁的范围

      锁分解的核心是将无关的代码块,如果在一个方法中有一部分的代码与锁无关,一部分的代码与锁有关,那么可以缩小这个锁的返回,这样锁操作的代码块就会减少,锁竞争的可能性也会减少

传统写法:

public synchronized void synchronizedOnMethod(){ //粗粒度直接在方法上加synchronized,这样会提高锁冲突的概率prefix();try {TimeUnit.SECONDS.sleep(1);}catch (InterruptedException e){}post();}private void post(){try {TimeUnit.SECONDS.sleep(1);}catch (InterruptedException e){}}private void prefix(){try {TimeUnit.SECONDS.sleep(1);}catch (InterruptedException e){}}}

修正写法

//假设prefix和post方法是线程安全的(与锁无关的代码)
static class SynchronizedClazz{public void mineSynOnMethod(){prefix();synchronized (this){ //synchronized代码块只保护有竞争的代码try {TimeUnit.SECONDS.sleep(1);}catch (InterruptedException e){}}post();}

减少锁的粒度

      如果一个锁需要保护多个相互独立的变量,那么可以将一个锁分解为多个锁,并且每个锁保护一个变量,比较对比下面的两段代码,

假设 allUsers和allComputers是两个相互独立的变量

传统写法

static class DecomposeClazz{private final Set<String> allUsers = new HashSet<String>();private final Set<String> allComputers = new HashSet<String>();public synchronized void addUser(String user){ //公用一把锁allUsers.add(user);}public synchronized void addComputer(String computer){allComputers.add(computer);}}

修正写法

static class DecompossClazz2{private final Set<String> allUsers = new HashSet<String>();private final Set<String> allComputers = new HashSet<String>();public void addUser(String user){ //分解为两把锁synchronized (allUsers){allUsers.add(user);}}public void addComputer(String computer){synchronized (allComputers){allComputers.add(computer);}}}

锁分段

      如上的方法把一个锁分解为2个锁时候,采用两个线程时候,大约能够使程序的效率提升一倍,但是当竞争激烈的时候,单一个锁上面的竞争还是很激烈,我们还可以将锁分解技术进一步扩展到一组独立的对象例如ConcurrentHashMap的锁分段技术

package com.qunar.des.lock;
import java.util.HashMap;
import java.util.Map;
/*** Created by chenglaiguo on 8/14/15.*/
public class MyConcurrentHashMap<K,V> {private final int LOCK_COUNT = 16;private final Map<K,V> map;private final Object[] locks ;public MyConcurrentHashMap() {this.map = new HashMap<K,V>();locks = new Object[LOCK_COUNT];for (int i=0;i<LOCK_COUNT;i++){locks[i] = new Object();}}private int keyHashCode(K k){return Math.abs(k.hashCode() % LOCK_COUNT);}public V get(K k){int keyHashCode = keyHashCode(k);synchronized (locks[keyHashCode % LOCK_COUNT]){return map.get(k);}}}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/326981.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

云计算设计模式(五)——计算资源整合模式

合并多个任务或操作成一个单一的计算单元。这种模式可以提高计算资源的利用率&#xff0c;并降低与云托管的应用程序进行计算处理相关的成本和管理开销。 背景和问题 云应用程序频繁执行各种操作。在某些解决方案也可能是有意义的最初遵循的关注点分离的设计原则&#xff0c;并…

stream获取filter

Java集合Stream类filter的使用_黄嘉成的博客-CSDN博客 Java集合Stream类filter的使用 黄嘉成 2018-05-11 11:49:42 242767 收藏 116 分类专栏&#xff1a; Java高级编程 文章标签&#xff1a; java 集合 Stream filter 过滤 版权 Java高级编程 专栏收录该内容 4 篇文章0 订…

MySQL数据库开发的 36 条军规

转载自 MySQL数据库开发的 36 条军规 核心军规 尽量不在数据库做运算 控制单表数据量 纯INT不超过10M条&#xff0c;含Char不超过5M条 保持表身段苗条 平衡范式和冗余 拒绝大SQL&#xff0c;复杂事务&#xff0c;大批量任务 字段类军规 用好数值字段&#xff0c;尽量简化…

mybatis简单案例源码详细【注释全面】——测试层(UserMapperTest.java)

/** * Title: UserMapperTest.java * Package org.test * Description: TODO该方法的主要作用&#xff1a; * author A18ccms A18ccms_gmail_com * date 2017-10-5 下午7:51:50 * version V1.0 */ package org.test;import java.io.IOException; import java.io.InputStr…

Visual Studio 2017 RC3支持.NET Core,延迟对Python的支持

Visual Studio 2017第三个候选版本上周发布&#xff0c;解决了之前发现的安装程序的小问题。由于这些问题得到了解决&#xff0c;现在值得关注的就是这次版本中更新了什么内容。&#xff08;版本是发布于1月27日的build 26127.00&#xff09; RC3版本中最值得关注的部分就是对N…

双向链表的(CRUD)

代码实现(CRUD) package com.atguigu.linkedlist;/*** 创建人 wdl* 创建时间 2021/3/19* 描述*/ public class DoubleLinkedListDemo {public static void main(String[] args) {//测试System.out.println("双向链表的测试");HeroNode2 hearo1 new HeroNode2(1, &q…

java读取Resources下文件

java读取Resources下文件_杰子的世界-CSDN博客_java获取resources下的文件 第四种&#xff0c; 读取路径 ResourceBundle bundle ResourceBundle.getBundle("config"); String url bundle.getString("url"); 1 2 该方法默认读取的是resources文件夹下的以…

达到年薪 40W 必需掌握的技术。

转载自 达到年薪 40W 必需掌握的技术。 很多人在问我&#xff0c;程序员如何拿高薪&#xff0c;如何做到年薪40W&#xff0c;其实总结出来还是一句话&#xff0c;你的技术决定你的能力已经薪资。 那么什么样的技术人才才能拿到一份Java行业里面的高薪呢&#xff1f;下面是我…

mybatis简单案例源码详细【注释全面】——Utils层(MybatisUtils.java)

/** * Title: MybatisUtils.java * Package org.util * Description: TODO该方法的主要作用&#xff1a; * author A18ccms A18ccms_gmail_com * date 2017-10-5 下午8:38:14 * version V1.0 */ package org.util;import java.io.IOException; import java.io.InputStrea…

虚拟研讨会:.NET的未来在哪里?

.NET生态系统在过去的一年中发生了很多事情。在几个方面发展非常迅速&#xff1a;Xamari、UWP、.NET Core、.NET native、F#和开源等等。 如果要关注细节&#xff0c;那大的景象难以描绘。因为在每个方面都有新的动作&#xff1a;跨平台、云、移动、Web应用和通用应用。开发人员…

iOS Charles 抓包

iOS Charles 抓包指南 - 从入门到精通_VictorZhang-CSDN博客_charles ios 下载安装包 Download a Free Trial of Charles • Charles Web Debugging Proxy

使用Servlet上传多张图片——访问提示

上传文件&#xff0c;我们在做项目中补课避免的&#xff0c;有时候我们需要上传单张或者单个文件&#xff0c;但是有时候我们就需要上传多个文件或者多张图片了&#xff0c;我们这里以多张&#xff08;4张&#xff09;图片为例&#xff0c;再多也都是一样的概念&#xff0c;接下…

云计算设计模式(六)——命令和查询职责分离(CQRS)模式

隔离&#xff0c;通过使用不同的接口&#xff0c;从操作读取数据更新数据的操作。这种模式可以最大限度地提高性能&#xff0c;可扩展性和安全性;支持系统在通过较高的灵活性&#xff0c;时间的演变;防止更新命令&#xff0c;从造成合并在域级别上的冲突。 背景和问题 在传统的…

Intellij IDEA 那些隐藏好用的小技巧

转载自 Intellij IDEA 那些隐藏好用的小技巧 概述 之前写了一篇介绍IntellIJ IDEA的文章《 Intellij Idea非常6的10个姿势 》&#xff0c;主要是列出一些平时大家可能没用过或者没怎么用&#xff0c;但是又非常好用的IntellIJ IDEA小技巧。由于篇幅原因&#xff0c;只是列出了…

约瑟夫(环)问题(Josephu)(单向环形链表)

问题描述 代码实现 package com.atguigu.linkedlist;import com.sun.org.apache.bcel.internal.generic.NEW;/*** 创建人 wdl* 创建时间 2021/3/19* 描述*/ public class Josepfu {public static void main(String[] args) {//测试一把看看构建的环形链表和遍历是否正确Circle…

使用Servlet上传多张图片——实体层(ProductInfo.java)

package orz.treeSquirrels.entity; /*** 商品信息表的实体类* author Administrator**/ public class ProductInfo {private int productId; //商品编号private String productName; //商品名称private float price; //商品价格private String details; //商品详情…

vue+vscode+nodejs 开发环境搭建

参考文献 vuevscodenodejs 开发环境搭建 - Desperador - 博客园 nodejs 指定全局安装路径和缓存路径 - Curedfisher - 博客园 安装配置nodejs并创建Vue项目 vscode下载地址&#xff1a; Documentation for Visual Studio Code nodejs安装配置 1.下载 地址&#xff1a; …

用数组模拟栈

思路分析 代码实现 package com.atguigu.stack;import com.sun.org.apache.xml.internal.dtm.ref.sax2dtm.SAX2DTM2;import java.net.ServerSocket; import java.util.ArrayList; import java.util.Scanner; import java.util.Stack;/*** 创建人 wdl* 创建时间 2021/3/20* 描述…

Redis PK Memcached,哪个更牛叉

转载自 Redis PK Memcached&#xff0c;哪个更牛叉 说到 redis 就会联想到 memcached&#xff0c;反之亦然。了解过两者的同学有那么个大致的印象&#xff1a; redis 与 memcached 相比&#xff0c;不仅支持简单的 key-value 数据类型&#xff0c;同时还提供 list,set,zset,ha…