并发环境下进行编程时,需要使用锁机制来同步多线程间的操作,保证共享资源的互斥访问。加锁会带来性能上的损坏,似乎是众所周知的事情。然而,加锁本身不会带来多少的性能消耗,性能主要是在线程的获取锁的过程。如果只有一个线程竞争锁,此时并不存在多线程竞争的情况,那么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 一起交流

java多线程编程——锁优化相关推荐

  1. Java多线程编程 — 锁优化

    2019独角兽企业重金招聘Python工程师标准>>> 阅读目录 一.尽量不要锁住方法 二.缩小同步代码块,只锁数据 三.锁中尽量不要再包含锁 四.将锁私有化,在内部管理锁 五.进行 ...

  2. java单线程上锁_关于Java多线程编程锁优化的深入学习

    正文 并发环境下进行编程时,需要使用锁机制来同步多线程间的操作,保证共享资源的互斥访问.加锁会带来性能上的损坏,似乎是众所周知的事情.然而,加锁本身不会带来多少的性能消耗,性能主要是在线程的获取锁的过 ...

  3. Java多线程编程—锁优化

    并发环境下进行编程时,需要使用锁机制来同步多线程间的操作,保证共享资源的互斥访问.加锁会带来性能上的损坏,似乎是众所周知的事情.然而,加锁本身不会带来多少的性能消耗,性能主要是在线程的获取锁的过程.如 ...

  4. java多线程编程01---------基本概念

    一. java多线程编程基本概念--------基本概念 java多线程可以说是java基础中相对较难的部分,尤其是对于小白,次一系列文章的将会对多线程编程及其原理进行介绍,希望对正在多线程中碰壁的小 ...

  5. Java多线程编程那些事:volatile解惑--转

    http://www.infoq.com/cn/articles/java-multi-thread-volatile/ 1. 前言 volatile关键字可能是Java开发人员"熟悉而又陌 ...

  6. Java多线程编程:交替打印数字1234和字母abcd

    Java多线程编程:交替打印数字1234和字母abcd 1. 使用synchronized同步锁 2. 使用LockSupport类 2.1 LockSupport介绍 3. 使用AtomicInte ...

  7. Java多线程开发(一)Java多线程编程简介

    文章目录 参考 Java线程简介 Thread类构造方法和属性 常用Thread类方法 线程的生命周期 多线程编程的优势和风险 安全性问题 活跃性问题 性能问题 参考 [Java并发系列01]Thre ...

  8. Java 多线程编程核心技术

    课程介绍 多线程编程在最大限度利用计算资源.提高软件服务质量方面扮演着至关重要的角色,而掌握多线程编程也成为了广大开发人员所必须要具备的技能. 本课程以基本概念.原理方法为主线,每篇文章结合大量演示实 ...

  9. Java多线程编程模式实战指南(二):Immutable Object模式--转载

    本文由本人首次发布在infoq中文站上:http://www.infoq.com/cn/articles/java-multithreaded-programming-mode-immutable-o ...

最新文章

  1. 【剑指offer-Java版】26复杂链表的复制
  2. 对于二叉树三种非递归遍历方式的理解
  3. python leetcode_leetcode 刷题经验,主力 python
  4. 神经网络 卷积神经网络_如何愚弄神经网络?
  5. [JavaScript]项目优化总结
  6. What's the difference between Unicode and UTF-8?
  7. 字体系列之字体大小(CSS、HTML)
  8. java堆栈_Java堆栈– Java堆栈
  9. Vova and Train (codeforces 1066A)
  10. win7 便签快捷键
  11. dvwa-sql盲注
  12. 【深度学习】卷积神经网络原理
  13. 井字游戏HTML,HTML5井字棋游戏
  14. linux 命令:less详解
  15. 怎么用python编简单游戏大全_适合新手练手的三个python简单小游戏
  16. 如何判断二叉树的前序,中序,后序遍历
  17. 1 buffers were freed while being dequeued
  18. 泛微OA 子表单中文本框设置默认值不显示的问题
  19. 全国计算机考的是ms还是mps,请问有没有人了解Cornell的MPS program啊
  20. @SpringbootApplication注释是什么意思?

热门文章

  1. inur new.php id,Cmsez(随易)全站系统注入0day
  2. 如何忽略证书继续访问_前5个最容易被忽视的可访问性问题
  3. 1月3日学习内容整理:modelform
  4. 最简单 - 单例模式
  5. 1Python全栈之路系列Web框架介绍
  6. 数据库监控框架 oneproxy-monitor 开源了
  7. VSAN见证虚拟设备
  8. NSString 字符串 操作 常用
  9. mysql int 11 java_mysql中int(11)列的大小(以字节为单位)是多少?
  10. seo每日一贴_白杨SEO:我看ZAC的外贸SEO应该怎样做?(策略篇)