java多线程编程——锁优化

并发环境下进行编程时,需要使用锁机制来同步多线程间的操作,保证共享资源的互斥访问。加锁会带来性能上的损坏,似乎是众所周知的事情。然而,加锁本身不会带来多少的性能消耗,性能主要是在线程的获取锁的过程。如果只有一个线程竞争锁,此时并不存在多线程竞争的情况,那么JVM会进行优化,那么这时加锁带来的性能消耗基本可以忽略。因此,规范加锁的操作,优化锁的使用方法,避免不必要的线程竞争,不仅可以提高程序性能,也能避免不规范加锁可能造成线程死锁问题,提高程序健壮性。下面阐述几种锁优化的思路。

一、尽量不要锁住方法

在普通成员函数上加锁时,线程获得的是该方法所在对象的对象锁。此时整个对象都会被锁住。这也意味着,如果这个对象提供的多个同步方法是针对不同业务的,那么由于整个对象被锁住,一个业务业务在处理时,其他不相关的业务线程也必须wait。下面的例子展示了这种情况:

LockMethod类包含两个同步方法,分别在两种业务处理中被调用:

复制代码
public class LockMethod {
public synchronized void busiA() {
for (int i = 0; i < 10000; i++) {
System.out.println(Thread.currentThread().getName() + “deal with bussiness A:”+i);
}
}
public synchronized void busiB() {
for (int i = 0; i < 10000; i++) {
System.out.println(Thread.currentThread().getName() + “deal with bussiness B:”+i);
}
}
}

BUSSA是线程类,用来处理A业务,调用的是LockMethod的busiA()方法:
public class BUSSA extends Thread {
LockMethod lockMethod;
void deal(LockMethod lockMethod){
this.lockMethod = lockMethod;
}

@Override
public void run() {super.run();lockMethod.busiA();
}
123456复制代码

}

BUSSB是线程类,用来处理B业务,调用的是LockMethod的busiB()方法:
public class BUSSB extends Thread {
LockMethod lockMethod;
void deal(LockMethod lockMethod){
this.lockMethod = lockMethod;
}

@Override
public void run() {super.run();lockMethod.busiB();
}
123456复制代码

}
TestLockMethod类,使用线程BUSSA与BUSSB进行业务处理:
public class TestLockMethod extends Thread {

public static void main(String[] args) {LockMethod lockMethod = new LockMethod();BUSSA bussa = new BUSSA();BUSSB bussb = new BUSSB();bussa.deal(lockMethod);bussb.deal(lockMethod);bussa.start();bussb.start();}
1234567891011复制代码

}
运行程序,可以看到在线程bussa 执行的过程中,bussb是不能够进入函数 busiB()的,因为此时lockMethod 的对象锁被线程bussa获取了。

二、缩小同步代码块,只锁数据

有时候为了编程方便,有些人会synchnoized很大的一块代码,如果这个代码块中的某些操作与共享资源并不相关,那么应当把它们放到同步块外部,避免长时间的持有锁,造成其他线程一直处于等待状态。尤其是一些循环操作、同步I/O操作。不止是在代码的行数范围上缩小同步块,在执行逻辑上,也应该缩小同步块,例如多加一些条件判断,符合条件的再进行同步,而不是同步之后再进行条件判断,尽量减少不必要的进入同步块的逻辑。

三、锁中尽量不要再包含锁

这种情况经常发生,线程在得到了A锁之后,在同步方法块中调用了另外对象的同步方法,获得了第二个锁,这样可能导致一个调用堆栈中有多把锁的请求,多线程情况下可能会出现很复杂、难以分析的异常情况,导致死锁的发生。下面的代码显示了这种情况:

synchronized(A){

synchronized(B){

  }  
12复制代码

}

或是在同步块中调用了同步方法:

synchronized(A){

B  b = objArrayList.get(0);
b.method(); //这是一个同步方法
123复制代码

}

解决的办法是跳出来加锁,不要包含加锁:
{
B b = null;

synchronized(A){
b = objArrayList.get(0);
}
b.method();
}

四、将锁私有化,在内部管理锁

把锁作为一个私有的对象,外部不能拿到这个对象,更安全一些。对象可能被其他线程直接进行加锁操作,此时线程便持有了该对象的对象锁,例如下面这种情况:
class A {
public void method1() {
}
}

class B {
public void method1() {
A a = new A();
synchronized (a) { //直接进行加锁
      a.method1();

    }
}
123复制代码

}

这种使用方式下,对象a的对象锁被外部所持有,让这把锁在外部多个地方被使用是比较危险的,对代码的逻辑流程阅读也造成困扰。一种更好的方式是在类的内部自己管理锁,外部需要同步方案时,也是通过接口方式来提供同步操作:
class A {
private Object lock = new Object();
public void method1() {
synchronized (lock){

    }
}
123复制代码

}

class B {
public void method1() {
A a = new A();
a.method1();
}
}

具有1-5工作经验的,面对目前流行的技术不知从何下手,需要突破技术瓶颈的可以加群。在公司待久了,过得很安逸,但跳槽时面试碰壁。需要在短时间内进修、跳槽拿高薪的可以加群。如果没有工作经验,但基础非常扎实,对java工作机制,常用设计思想,常用java开发框架掌握熟练的可以加群。java架构群:697579751 一起交流


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

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

相关文章

【QGIS入门实战精品教程】10.3:QGIS栅格DEM数据重复类方法案例汇总

QGIS栅格DEM数据重复类方法案例汇总:按表格重分类、按图层重分类。 参考阅读: 【GlobalMapper精品教程】029:栅格重分类案例详解 ArcGIS实验教程——实验四十三:ArcGIS栅格重分类(Reclass)案例详解 ArcGIS怎样获取重分类后各类所占的像元个数 文章目录 一、按表格分类二、…

QT添加rtmp库的时候出现问题

刚开始出现undefined reference to __chkstk的错误。 然后在vc里面找到chkstk.obj放到相关目录下并在工程文件直接添加&#xff1a; LIBS "E:\QTProjects\RTMP\RTMPDelayTest\librtmp\lib\chkstk.obj" 又出现了新的错误 E:\QTProjects\RTMP\RTMPDelayTest\librtmp\l…

@Before,@BeforeClass,@BeforeEach和@BeforeAll之间的区别

Before的代码在每次测试之前执行 BeforeClass在整个测试方法执行之前运行一次 如果您的测试类有十个测试&#xff0c;则Before代码将执行十次&#xff0c;但是BeforeClass将仅执行一次。 当多个测试需要共享相同的代码时&#xff0c;可以使用BeforeClass 。 建立数据库连接属于…

记一次 .NET 某工控自动化控制系统 卡死分析

一&#xff1a;背景 1. 讲故事前段时间遇到了好几起关于窗体程序的 进程加载锁 引发的 程序卡死 和 线程暴涨 问题&#xff0c;这种 dump 分析难度较大&#xff0c;主要涉及到 Windows操作系统 和 C 的基础知识&#xff0c;所以有必要简单整理和大家分享一下&#xff0c;上 win…

BZOJ4573:[ZJOI2016]大森林——题解

http://www.lydsy.com/JudgeOnline/problem.php?id4573 https://www.luogu.org/problemnew/show/P3348#sub http://uoj.ac/problem/195 https://loj.ac/problem/2092 小Y家里有一个大森林&#xff0c;里面有n棵树&#xff0c;编号从1到n。一开始这些树都只是树苗&#xff0c;只…

Spring中神奇@aotuWrited

好久没有写博客了&#xff0c;放假就是充电学习的时候&#xff0c;的确一直是这样做的。来给自己一点掌声。我们还是进入今天的主题吧。 我们自己写代码一般会向下面这样干啊&#xff0c;因为这样简单&#xff0c;其余交给spring去做吧。Spring会自动把生成的userService注入进…

40个常用的springBoot注解

一、Spring Web MVC注解 RequestMapping RequestMapping注解的主要用途是将Web请求与请求处理类中的方法进行映射。 Spring MVC和Spring WebFlux都通过RquestMappingHandlerMapping和RequestMappingHndlerAdapter两个类来提供对RequestMapping注解的支持。 RequestMapping注解…

.NET MAUI 跨平台应用开发 I|.NET MAUI 跨平台基础

编辑&#xff1a;Alan Wang排版&#xff1a;Rani Sun微软 Reactor 为帮助广开发者&#xff0c;技术爱好者&#xff0c;更好的学习 .NET Core, C#, Python&#xff0c;数据科学&#xff0c;机器学习&#xff0c;AI&#xff0c;区块链, IoT 等技术&#xff0c;将每周三到周六&…

走出宣传,国产VR手机盒子到底哪家强?

国产VR手机盒子作为入门机是一个不错的选择&#xff0c;不过你知道哪一款更适合你吗&#xff1f; 从去年看虚拟现实还是一个遥不可及的梦&#xff0c;今年却真正的火起来了。各大厂商纷纷推出自家的VR设备&#xff0c;宣传活动如火如荼。爱尝鲜的你是否按耐不住? 如果你觉得动…

Shell 学习笔记之运算符

基本运算符 算术运算符 val expr 2 2 需要注意的是 表达式和运算符之间需要有空格&#xff08;比如2 2&#xff0c;不能是22&#xff09;两边最外面的字符是&#xff0c;在esc键下面&#xff0c;不是引号哦乘号* 前面必须加上反斜杠 \ 才能实现乘法效果&#xff0c;比如 exp…

POJ 2353 DP

双向DP记录路径。 // by SiriusRen #include <stack> #include <cstdio> #include <cstring> using namespace std; stack<int>s; int n,m,RECL,RECR,minn0x3fffffff,a[555][555],f[555][555],recl[555][555],recr[555][555]; int main(){memset(f,0x3…

【ArcGIS Pro微课1000例】0024:自定义坐标系统---以阿尔伯斯投影(Albers)为例

在实际工作中,经常需要进行矢量数据或栅格数据的投影转换工作,但有时候ArcGIS中恰恰没有我们需要的坐标系,此时,就需要我们自定义坐标系。本文以阿尔伯斯投影(Albers)为例,讲解自定义投影的一般过程及注意事项。 文章目录 一、自定义坐标系二、投影转换一、自定义坐标系…

Linux 操作必备 150 个命令

linux 命令是对 Linux 系统进行管理的命令。对于 Linux 系统来说&#xff0c;无论是中央处理器、内存、磁盘驱动器、键盘、鼠标&#xff0c;还是用户等都是文件&#xff0c; Linux 系统管理的命令是它正常运行的核心&#xff0c;与之前的 DOS 命令类似。 linux 命令在系统中有两…

dotnet 6 为什么网络请求不跟随系统网络代理变化而动态切换代理

本文记录在 dotnet 6 的网络和在 .NET Framework 的行为的变更。在 dotnet 6 下&#xff0c;默认的网络请求在系统网络代理变更的时候&#xff0c;是不会动态切换代理的。例如在应用运行进行网络通讯之后&#xff0c;打开 Fiddler 抓包&#xff0c;此时将会发现 Fiddler 抓不到…

旧金山参议员提议发布“封杀令”,理由是马路不为机器人所服务

说实话&#xff0c;这个理由有够奇葩。 因为快递无人机所受限制颇多&#xff0c;渐渐地&#xff0c;越来越多的快递机器人被研制出来&#xff08;这里的“机器人”&#xff0c;包括无人车和及机器人&#xff09;&#xff0c;用于城市的快递发送&#xff0c;比如国内的京东无人…

Socket编程:之双机通信

服务端&#xff1a; 1 #include<sys/socket.h>2 #include<sys/types.h>3 #include<stdio.h>4 #include<unistd.h>5 #include<stdlib.h>6 #include<string.h>7 #include<netdb.h>8 #include<netinet/in.h>9 #include<arpa/i…

jquery中$each()

$.each()&#xff1a;可用于遍历任何的集合(无论是数组或对象) $(selector).each()&#xff1a;专用于jquery对象的遍历, 如果是数组,回调函数每次传入数组的索引和对应的值(值亦可以通过this 关键字获取,但javascript总会包装this 值作为一个对象—尽管是一个字符串或是一个数…

【QGIS入门实战精品教程】7.2:QGIS点状数据符号化设置案例教程

点状符号化的类型有:单一符号、分类、渐进、基于规则、点的位移、点聚类、热图。 相关阅读: 【QGIS入门实战精品教程】7.1:QGIS面状数据符号化设置案例教程 文章目录 一、单一符号二、分类三、渐进四、基于规则五、点的位移六、点聚类七、热图一、单一符号 跟面状符号一样,…

SpringCloud与Dubbo的比较

Dubbo 一、dubbo简介 Dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架&#xff0c;使得应用可通过高性能的RPC实现服务的输出和输入功能&#xff0c;可以和Spring框架无缝集成。 Dubbo是一款高性能、轻量级的开源Java RPC框架&#xff0c;它提供了三大核心能力&#xff…

VR 技术加上 8K 画质! 2016 年里约奥运会亮点十足

据报道&#xff0c;2016 年里约奥运会将运用到 VR 技术。 最近&#xff0c;奥林匹克广播服务公司&#xff08;OBS&#xff09;表示出对虚拟现实技术的兴趣&#xff0c;其实用虚拟现实技术报道赛事已经不是什么新鲜的事了&#xff0c;之前 NBA 就这样做过&#xff0c;但是将奥运…