RSA解密 优化 的原理详解 ,synchronized的使用
一、 原来代码
-
示例代码:
private static org.bouncycastle.jce.provider.BouncyCastleProvider bouncyCastleProvider = null; public static org.bouncycastle.jce.provider.BouncyCastleProvider getBouncyCastleProviderInstance() { if (bouncyCastleProvider == null) { bouncyCastleProvider = new org.bouncycastle.jce.provider.BouncyCastleProvider(); } return bouncyCastleProvider; }
二、 优化后代码
-
示例代码:
private static volatile org.bouncycastle.jce.provider.BouncyCastleProvider bouncyCastleProvider ; public static org.bouncycastle.jce.provider.BouncyCastleProvider getBouncyCastleProviderInstance() { if (bouncyCastleProvider == null) { synchronized(org.bouncycastle.jce.provider.BouncyCastleProvider.class){ if(bouncyCastleProvider == null){ bouncyCastleProvider = new org.bouncycastle.jce.provider.BouncyCastleProvider(); } } } return bouncyCastleProvider; }
三、实现原理
-
添加synchronized关键字。添加到同步代码块中,而不是如下:
public static synchronized org.bouncycastle.jce.provider.BouncyCastleProvider getBouncyCastleProviderInstance() { if (bouncyCastleProvider == null) { bouncyCastleProvider = new org.bouncycastle.jce.provider.BouncyCastleProvider(); } return bouncyCastleProvider; }
- 目的:即:保证在同一时刻最多只有一个线程执行该段代码,达到保证并发安全的效果。
四 、 synchronized
-
定义
- synchronized锁是重量级锁,重量级体现在活跃性差一点。synchronized锁是内置锁,意味着JVM能基于synchronized锁做一些优化:比如增加锁的粒度(锁粗化)、锁消除。
- synchronized锁释放是自动的,当线程执行退出synchronized锁保护的同步代码块时,会自动释放synchronized锁。
- 线程在竞争synchronized锁时是非公平的。
-
synchronized Java中的关键字,是一种同步锁。它修饰的对象有以下几种:
- 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
- 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
- 修饰一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
- 修饰一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。
-
使用
-
1、 普通同步方法,锁的是当前实例的对象
- 同步方法锁住的是调用方法的对象;新创建的对象调用方法,和之前的方法不同步。
class mYread implements Runnable { private static int count; public mYread() { count = 0; } public synchronized void method() { for (int i = 0; i < 5; i ++) { try { System.out.println(Thread.currentThread().getName() + ":" + (count++)); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } public synchronized void run() { method(); } } //执行调用 mYread read1 = new mYread(); mYread read2 = new mYread(); Thread thread1 = new Thread(read1, "mYread1"); Thread thread2 = new Thread(read2, "mYread2"); thread1.start(); thread2.start(); read1 和 read2 是两个对象,thread1和thread2执行不会保持线程同步。
-
2、 静态同步方法,锁的是静态方法所在的类对象
- 静态同步方法锁的是类的对象,新创建的对象也是被锁的对象。
class mYread implements Runnable { private static int count; public mYread() { count = 0; } public synchronized static void method() { for (int i = 0; i < 5; i ++) { try { System.out.println(Thread.currentThread().getName() + ":" + (count++)); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } public synchronized void run() { method(); } } //执行调用 mYread read1 = new mYread(); mYread read2 = new mYread(); Thread thread1 = new Thread(read1, "mYread1"); Thread thread2 = new Thread(read2, "mYread2"); thread1.start(); thread2.start(); read1 和 read2 是两个对象,但在thread1和thread2并发执行时却保持了线程同步。
-
3、 同步代码块,锁的是括号里的对象。(此处的可以是实例对象,也可以是类的class对象。)
-
指定给某个对象加锁
> 如果有一个明确的对象:
public abstract class RSACoderUtils extends CoderUtils { if (bouncyCastleProvider == null) { synchronized(org.bouncycastle.jce.provider.BouncyCastleProvider.class){ if(bouncyCastleProvider == null){ bouncyCastleProvider = new org.bouncycastle.jce.provider.BouncyCastleProvider(); } } } }
> 如果没有一个明确的对象:
public abstract class RSACoderUtils extends CoderUtils { if (bouncyCastleProvider == null) { private byte[] lock = new byte[0]; // 特殊的instance变量 synchronized(lock){ if(bouncyCastleProvider == null){ bouncyCastleProvider = new org.bouncycastle.jce.provider.BouncyCastleProvider(); } } } }
-. 比较两种创建对象的消耗:
Object lock = new Object(); private byte[] lock = new byte[0];
通过查看编译后的字节码:生成零长度的byte[]的lock需要3行操作码,Object 的lock 则需要7行操作码,故零长度的byte数组对象创建性能更好。
-
给某个类加锁
public abstract class RSACoderUtils extends CoderUtils { public void test(){ synchronized(RSACoderUtils.class){ if(bouncyCastleProvider == null){ bouncyCastleProvider = new org.bouncycastle.jce.provider.BouncyCastleProvider(); } } } }
-
-
五、volatile
- 禁止指令重排序优化
- 保证此变量对所有线程的可 见性,这里的“可见性”是指当一条线程修改了这个变量的值,新值对于其他线程来说是可以 立即得知的。
六、 单例模式
- 保证一个类仅有一个实例,并提供一个访问它的全局访问点。
-
懒汉模式 :
public class Monitor { private static Monitor monitor = null; private static volatile Monitor monitor = null; // private Monitor() {} public static Monitor getMonitor() { if (monitor == null) { synchronized (Monitor.class) { if (monitor == null) { monitor = new Monitor(); } } } return monitor; } }
-
饿汉模式:
public class Monitor { private static Monitor monitor = new Monitor (); private Monitor () {} public static Monitor getMonitor() { return monitor; } }
欢迎关注公众号,查看更多内容 :
volatile 关键字的详细介绍;
synchronized 关键字的详解;

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
只需4个步骤,分析解决在生产环境下JVM内存泄露问题
作者:未完成交响曲 发现异常 首先通过我们内部搭建的日志平台发现我们线上环境一个java应用有大量的http接口请求超时,登录linux服务器查看网络环境没有问题,判断是应用自身运行异常,重启应用后发现异常还在,开始查找问题。 初步查找问题 通过指令:jstat -gcutil 查看jvm内存占用和gc情况: 发现老年代内存占用比例过高,并且每次fullGC后并没有有效回收。老年代内存占用百分比变化趋势大致如下: 初步判断大量请求超时和服务瘫痪的直接原因: 每次fullGC后的内存占用越来越高 内存占用增长速度越来越快 fullGC的频率越来越高 最终占用达到100%,服务完全瘫痪 分析处理 使用指令:jmap -histo:live * | more 查看堆内存中的对象数量和大小 发现Log4jLogEvent这个对象实例很多,占用内存也异常的大,初步分析是异步日志传输速度跟不上,导致日志对象堆积在内存中。尝试使用调整Flume传输日志参数:提高flume单次传输量,减少最大延迟时间重启应用并监控接口调用情况发现应用暂时恢复正常了。 后续分析 在前一步分析内存的同时,使用指令:jma...
-
下一篇
Volatile 关键字
一、 定义 Java虚拟机提供的最轻量级的同步机制。 二、通过volatile关键字修饰后,具备两种特性 保证此变量对所有线程的可见性,这里的“可见性”是指当一条线程修改了这个变量的值,新值对于其他线程来说是可以 立即得知的。 普通变量不能做到这一点,普通变量的值在线程间传递均需要通过主内存来完成,例如,线程A修改一个普通变量的值, 然后向主内存进行回写,另外一条线程B在线程A回写完成了之后再从主内存进行读取操作,新变量值才会对线程B可见。 禁止指令重排序优化。 通过一个单例模式来讲解,代码如下: publicclassMonitors{ privatestaticvolatileMonitorsmonitors=null; privateMonitors(){} publicstaticMonitorsgetMonitor(){ if(monitor==null){ synchronized(Monitors.class){ if(monitors==null){ monitors=newMonitors(); } } } returnmonitors; } } 分析代码 monit...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- MySQL数据库在高并发下的优化方案
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Windows10,CentOS7,CentOS8安装Nodejs环境
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- 设置Eclipse缩进为4个空格,增强代码规范
- Docker容器配置,解决镜像无法拉取问题