Java使用同步解决线程安全问题的弊端

Java使用同步解决线程安全问题的弊端及带来的问题

一、多线程使用同步解决方案引入的问题

由于多线程会引入线程安全问题,我们使用了同步或者加锁的方法来解决这个问题,但是使用同步的方法也会带来相应的弊端。
主要有如下两个弊端:
1、使用同步的方法效率低
2、如果出现同步嵌套,会出现死锁问题。
对于第一个问题,告诉我们要慎用同步,只在必要的位置添加同步方法,而不是为了安全添加不必要的同步,这样会导致效率的降低,因为如果使用了同步会有锁机制,执行相关代码前会对锁进行相应的检查,这样就会降低效率。第二个问题是主要讲解的问题,这个我们需要在程序中尽量避免,如果出现死锁问题,会导致所有的工作都无法正常完成,陷入相互等待的状态。

二、死锁案例

通过一段代码来直观的了解死锁发生的场景。代码如下:
package com.example.thread.one;

public class DieLockDemo {
	
	public static void main(String[] args) {
		Object lockA = new Object();
		Object lockB = new Object();
		
		MyThread myThread1 = new MyThread(true, lockA, lockB);
		MyThread myThread2 = new MyThread(false, lockA, lockB);
		
		myThread1.setName("线程1");
		myThread2.setName("线程2");
		
		myThread1.start();
		myThread2.start();
	}

}

class MyThread extends Thread{
	private boolean flag;
	private Object lockA;
	private Object lockB;

	public MyThread(boolean flag, Object lockA, Object lockB) {
		super();
		this.flag = flag;
		this.lockA = lockA;
		this.lockB = lockB;
	}

	@Override
	public void run() {
		super.run();
		if(flag){
			synchronized (lockA) {
				System.out.println(Thread.currentThread().getName() + " :if lockA");
				synchronized (lockB) {
					System.out.println(Thread.currentThread().getName() + " :if lockB");
				}
			}
		}else{
			synchronized (lockB) {
				System.out.println(Thread.currentThread().getName() + " :else lockB");
				synchronized (lockA) {
					System.out.println(Thread.currentThread().getName() + " :else lockA");
				}
			}
		}
	}
}

上边程序可能出现的运行结果如下:

分析出现的原因:
当线程1获取的lockA的锁后执行完System.out.println(Thread.currentThread().getName() + " :if lockA");语句后时间片用完,线程2获取到时间片并且进入运行状态,线程2获取到lockB的锁后执行System.out.println(Thread.currentThread().getName() + " :else lockB");后需要获取lockA的锁,发现线程1还没有释放lockA的锁,因此进入阻塞状态,接下来线程1进入运行状态,同样的,线程1接着执行发现需要lockB的锁,但是这个锁被线程2使用也没有释放,此时线程1也进入阻塞状态。这样就产生了所谓的死锁问题,线程1和线程2相互等待,都无法执行接下来的代码。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值