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();
}
}
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();
}
}
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();
}
}
运行程序,可以看到在线程bussa 执行的过程中,bussb是不能够进入函数 busiB()的,因为此时lockMethod 的对象锁被线程bussa获取了。
二、缩小同步代码块,只锁数据
有时候为了编程方便,有些人会synchnoized很大的一块代码,如果这个代码块中的某些操作与共享资源并不相关,那么应当把它们放到同步块外部,避免长时间的持有锁,造成其他线程一直处于等待状态。尤其是一些循环操作、同步I/O操作。不止是在代码的行数范围上缩小同步块,在执行逻辑上,也应该缩小同步块,例如多加一些条件判断,符合条件的再进行同步,而不是同步之后再进行条件判断,尽量减少不必要的进入同步块的逻辑。
三、锁中尽量不要再包含锁
这种情况经常发生,线程在得到了A锁之后,在同步方法块中调用了另外对象的同步方法,获得了第二个锁,这样可能导致一个调用堆栈中有多把锁的请求,多线程情况下可能会出现很复杂、难以分析的异常情况,导致死锁的发生。下面的代码显示了这种情况:
synchronized(A){
synchronized(B){
}
- 1
- 2
}
或是在同步块中调用了同步方法:
synchronized(A){
B b = objArrayList.get(0);
b.method(); //这是一个同步方法
}
解决的办法是跳出来加锁,不要包含加锁: { 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();
}
}
}
这种使用方式下,对象a的对象锁被外部所持有,让这把锁在外部多个地方被使用是比较危险的,对代码的逻辑流程阅读也造成困扰。一种更好的方式是在类的内部自己管理锁,外部需要同步方案时,也是通过接口方式来提供同步操作: class A { private Object lock = new Object(); public void method1() { synchronized (lock){
}
}
}
class B { public void method1() { A a = new A(); a.method1(); } }
具有1-5工作经验的,面对目前流行的技术不知从何下手,需要突破技术瓶颈的可以加群。在公司待久了,过得很安逸,但跳槽时面试碰壁。需要在短时间内进修、跳槽拿高薪的可以加群。如果没有工作经验,但基础非常扎实,对java工作机制,常用设计思想,常用java开发框架掌握熟练的可以加群。java架构群:697579751 一起交流
java多线程编程——锁优化的更多相关文章
- Java多线程编程 — 锁优化
阅读目录 一.尽量不要锁住方法 二.缩小同步代码块,只锁数据 三.锁中尽量不要再包含锁 四.将锁私有化,在内部管理锁 五.进行适当的锁分解 正文 并发环境下进行编程时,需要使用锁机制来同步多线程间 ...
- Java多线程编程—锁优化
并发环境下进行编程时,需要使用锁机制来同步多线程间的操作,保证共享资源的互斥访问.加锁会带来性能上的损坏,似乎是众所周知的事情.然而,加锁本身不会带来多少的性能消耗,性能主要是在线程的获取锁的过程.如 ...
- Java多线程之锁优化策略
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6561264.html 锁的优化策略 编码过程中可采取的锁优化的思路有以下几种: 1:减少锁持有时间 例如:对 ...
- Java多线程编程详解
转自:http://programming.iteye.com/blog/158568 线程的同步 由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题.Ja ...
- Java多线程编程实战指南(核心篇)读书笔记(五)
(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76730459冷血之心的博客) 博主准备恶补一番Java高并发编程相 ...
- java多线程编程01---------基本概念
一. java多线程编程基本概念--------基本概念 java多线程可以说是java基础中相对较难的部分,尤其是对于小白,次一系列文章的将会对多线程编程及其原理进行介绍,希望对正在多线程中碰壁的小 ...
- Java多线程编程那些事:volatile解惑--转
http://www.infoq.com/cn/articles/java-multi-thread-volatile/ 1. 前言 volatile关键字可能是Java开发人员“熟悉而又陌生”的一个 ...
- 《Java多线程编程实战指南(核心篇)》阅读笔记
<Java多线程编程实战指南(核心篇)>阅读笔记 */--> <Java多线程编程实战指南(核心篇)>阅读笔记 Table of Contents 1. 线程概念 1.1 ...
- Java多线程编程实战02:多线程编程模型
多线程编程模型 线程安全名词 串行.并发和并行 串行:一个人,将任务一个一个完成 并发:一个人,有策略地同时做多件事情 并行:多个人,每人做一个事情 竞态 名词 竞态:计算结果的正确性与时间有关的现象 ...
随机推荐
- hadoop问题: bin/hadoop fs -ls ls: `.': No such file or directory
问题描述:bin/hadoop fs -ls ls: `.': No such file or directory 问题分析:版本问题,用法不同 https://stackoverflow.com/q ...
- Python3之数据类型
1.基本数据类型数字类型整型 int浮点型 float布尔型 bool: True==1.False==0复数类型 complex算术运算符 + - * / // % **赋值运算符 += -= *= ...
- Source Insight、Xshell(putty)、Xftp
body, table{font-family: 微软雅黑} table{border-collapse: collapse; border: solid gray; border-width: 2p ...
- FORTH基础
body, table{font-family: 微软雅黑} table{border-collapse: collapse; border: solid gray; border-width: 2p ...
- git 签出(恢复)指定文件
在项目开发中,偶尔会因为误删文件或其他原因需要从git仓库中恢复某些文件.此篇文章将介绍如何通过git从历史提交记录.分支记录恢复指定文件. 1. git checkout 说明:使用git chec ...
- python_猜年龄
猜年龄,有三次机会,如何做? 1. 检查 输入的数据是否合法,通过异常try来处理,并记录 输入错误次数 2. 通过累加器,判断是否猜了3次,并提示还剩余多少的机会 3. 当3次错误,跳出 #!/us ...
- junit测试延伸--私有方法测试
关于junit测试的延伸,这里有类概念级别的测试,继承类的测试,接口的测试,抽象类的测试,关于这些类级别的测试,这里我就不做多的赘述了. 关于上面的几个测试就是说,我们不应该单纯的去测试类中的一些方法 ...
- Linux下MongoDB安装和配置详解
1.下载安装包 将解压到/usr/local/mongodb 文件夹下 # mkdir /usr/local/mongodb # tar zxvf mongodb-linux-x86_64-3.2.9 ...
- 【转】利用matlab生成随机数函数
原文地址:利用matlab生成随机数函数 rand(n):生成0到1之间的n阶随机数方阵 rand(m,n):生成0到1之间的m×n的随机数矩阵 (现成的函数) betarnd:贝塔分布的随机数生成 ...
- GitHub For Beginners: Commit, Push And Go
In Part 1 of this two-part GitHub tutorial, we examined the main uses for GitHub and bega5n the proc ...