java多线程问题实践-01(重入锁)

java多线程项目问题实践-01(重入锁)

  • 程序运行时栈空了?
  • 进入调试
  • 分析为什么出现问题
  • 重入锁解决问题

程序运行时栈空了

在跟踪bug的时候,发现stack的前一秒有size,下一秒就被清空了。在对stack进行清空的操作只有在循环语句之后才有,而当前还在循环。

public class MainClass{

public void a(final B b){

Stack stack=b.getSatck();

for(..){
....
stack.pop();
....
stack.push();
}

stack.clear();
}

}

public Class B{

Stack stack;

public Stack  getSatck(){
  return stack;
}

}

其中B类是一个有关上下文的类,保存的栈是一个全局共享的变量。

发现在for循环中对栈取数据时报了空指针错误。

进入调试

在a方法打断点,发现进来了两个线程,同时在跑,下面为模拟图(省略具体的代码):

这里写图片描述

分析问题

分析上面的代码,结合调试堆栈:
此时如果有多个线程同时调用a方法,虽然每个MainClass对象执行不同的a方法,但是在B作为参数传进来的时候已经被申明位final,此时多个线程就共用了b,如果一个线程已经执行到清空栈的语句,而另一个线程刚好在做pop和push操作,就会出现栈空的情况,在对栈拿数据时就会报空指针错误了。

重入锁

这种问题就是属于多个线程同时对一个对象操作了,需要考虑加锁。但是加在哪里,怎么加才好一点?经过调试,发现在a方法直接加synchronized同步语句是不可行的,因为多个线程执行不是同个Mainclass对象,对a方法加锁在本例中无效。最后在b方法中申明一个全局静态的ReentrantLock锁,即可解决问题。改善后的代码如下:

public class MainClass{

public void a(final B b){

B.lock.lock();//获得全局锁

try{

Stack stack=b.getSatck();
for(..){
....
stack.pop();
....
stack.push();
}
stack.clear();

}
fianlly{
B.lock.unlock();//释放全局锁
}

}
}

public Class B{
public static ReentrantLock lock = new ReentrantLock();//申明全局锁
Stack stack;

public Stack  getSatck(){
  return stack;
}

}

总结

在代码中平时要考虑多种情况的多线程并发争用问题,不同的问题要具体分析,学会调试也是一种基本功。鉴于目前对多线程还需要加深理解,如有更好方法,欢迎补充。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值