干货分享!Java 多线程编程(锁优化)

news/2024/12/24 3:01:07

并发环境下进行编程时,需求运用锁机制来同步多线程间的操作,确保共享资源的互斥访问。

加锁会带来功能上的损坏,似乎是众所周知的事情。

然而,加锁本身不会带来多少的功能耗费,功能主要是在线程的获取锁的过程。

假如只要一个线程竞争锁,此时并不存在多线程竞争的情况,那么JVM会进行优化,那么这时加锁带来的功能耗费基本能够疏忽。

因此,标准加锁的操作,优化锁的运用方法,防止不必要的线程竞争,不只能够进步程序功能,也能防止不标准加锁或许形成线程死锁问题,进步程序健壮性。

下面论述几种锁优化的思路。

一、尽量不要锁住方法

在普通成员函数上加锁时,线程获得的是该方法所在对象的对象锁。此时整个对象都会被锁住。

这也意味着,如果这个对象提供的多个同步方法是针对不同业务的,那么由于整个对象被锁住,一个业务业务在处理时,其他不相关的业务线程也必须wait。

下面的例子展示了这种情况:

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

public class LockMethod {

public synchronized void busyA() {

for (int i = 0; i < 10000; i++) {

System.out.println(Thread.currentThread().getName() + “deal with bussiness A:”+i);

}

}

public synchronized void busyB() {

for (int i = 0; i < 10000; i++) {

System.out.println(Thread.currentThread().getName() + “deal with bussiness B:”+i);

}

}

}

BusyA是线程类,用来处理A业务,调用的是LockMethod的busyA()方法:

public class BusyA extends Thread {

LockMethod lockMethod;

void deal(LockMethod lockMethod){

this.lockMethod = lockMethod;

}

@Override

public void run() {

super.run();

lockMethod.busyA();

}

}

BusyB是线程类,用来处理B业务,调用的是LockMethod的busyB()方法:

public class BusyB extends Thread {

LockMethod lockMethod;

void deal(LockMethod lockMethod){

this.lockMethod = lockMethod;

}

@Override

public void run() {

super.run();

lockMethod.busyB();

}

}

TestLockMethod类,使用线程BusyA与BusyB进行业务处理:

public class TestLockMethod

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是不能够进入函数 busyB()的,因为此时lockMethod 的对象锁被线程bussa获取了。

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

有时候为了编程方便,有些人会synchnoized很大的一块代码。

如果这个代码块中的某些操作与共享资源并不相关,那么应当把它们放到同步块外部,避免长时间的持有锁,造成其他线程一直处于等待状态。

尤其是一些循环操作、同步I/O操作。不止是在代码的行数范围上缩小同步块,在执行逻辑上,也应该缩小同步块。

例如多加一些条件判断,符合条件的再进行同步,而不是同步之后再进行条件判断,尽量减少不必要的进入同步块的逻辑。

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

这种情况经常发生,线程在得到了A锁之后,在同步方法块中调用了另外对象的同步方法,获得了第二个锁.

这样可能导致一个调用堆栈中有多把锁的请求,多线程情况下可能会出现很复杂、难以分析的异常情况,导致死锁的发生。

下面的代码显示了这种情况:

synchronized(A){

synchronized(B){

}

}

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

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();

}

}

五、进行适当的锁分解

考虑下面这段程序:

public class GameServer {

public Map<String, List> tables = new HashMap<String, List>();

public void join(Player player, Table table) {

if (player.getAccountBalance() > table.getLimit()) {

synchronized (tables) {

List tablePlayers = tables.get(table.getId());

if (tablePlayers.size() < 9) {

tablePlayers.add(player);

}

}

}

}

public void leave(Player player, Table table) {/省略/}

public void createTable() {/省略/}

(搜索圈T社区,更多相关信息。更有免费行业相关视频教程哦!)
文章来源:公众号老九学堂


http://www.niftyadmin.cn/n/4788551.html

相关文章

Python Logging 模块完全解读(最全面的没有之一)

Python 中的 logging 模块可以让你跟踪代码运行时的事件&#xff0c;当程序崩溃时可以查看日志并且发现是什么引发了错误。Log 信息有内置的层级——调&#xff08;debugging&#xff09;、信息&#xff08;informational&#xff09;、警告&#xff08;warnings&#xff09;、…

使用 Theano 框架进行 MNIST 数字识别(纯干货,一点水没有)

概要&#xff1a;使用 Theano 机器学习框架&#xff0c;设计一个深度学习神经网络&#xff0c;对 MNIST 数据集进行手写数字识别。 &#xff08;想自学习编程的小伙伴请搜索圈T社区&#xff0c;更多行业相关资讯更有行业相关免费视频教程。完全免费哦!&#xff09; Theano 是…

Java中两变量三方法基础判断与理解

在这里首先先进行一个举例 package Text;//包名一般文件被其包裹在一个包里 public class Car { String color;//实例变量1 String paizi;//实例变量2 static int lunzi4;//静态变量 储存在指定地方。为一个类的基本信息如&#xff1a;车轮子4个 //构造方法不会产生返回值 如何…

一条SQL语句执行得很慢的原因到底有哪些?你不知道很有可能当误你的大事

说实话&#xff0c;这个问题可以涉及到 MySQL 的很多核心知识&#xff0c;可以扯出一大堆&#xff0c;就像要考你计算机网络的知识时&#xff0c;问你“输入URL回车之后&#xff0c;究竟发生了什么”一样&#xff0c;看看你能说出多少了。 之前腾讯面试的实话&#xff0c;也问…

数据结构中动态分配空间

1&#xff1a;就链式而言&#xff08;我个人比较喜欢链式因为链式缺少空间可以以加结点的形式来进行增加比较方便&#xff09; #include <iostream> #include <stdlib.h> using namespace std; void dongtaifenpei(){int *p;pnew int;&#xff08;new一个新的类型…

5个重要的人工智能预测(2019年)每个人都应该阅读

人工智能 - 特别是机器学习和深度学习 - 在2018年无处不在&#xff0c;并且预计未来12个月的炒作将不会消失。 当然&#xff0c;炒作最终会消亡&#xff0c;人工智能将成为我们生活中的另一个连贯的线索&#xff0c;就像互联网&#xff0c;电力和燃烧在过去几天一样。 但至少…

VMware 菜鸟教程

VMware下载与安装 一、 虚拟机的下载 进入VMware官网&#xff08;https://www.vmware.com/cn.html&#xff09;&#xff0c;可能会有一点慢&#xff0c;耐心等待。 点击下载&#xff0c;进入到如下页面 点击下载产品 可以看到这里有两个版本&#xff0c;windows和Linux版本&…

VMware tools详细教程 解决安装失败等问题

1、打开虚拟机VMware Workstation&#xff0c;启动Ubuntu系统&#xff0c;菜单栏 - 虚拟机 - 安装VMware Tools&#xff0c;不启动Ubuntu系统是无法点击“安装VMware Tools”选项的&#xff0c;如下图&#xff1a; 必须在虚拟机内部进行安装&#xff01;&#xff01;&#xff0…