在日常开发中我们经常会遇到多线程Debug调试,
一般我们都是利用Spring Boot对外提供接口,Tomcat中在有多人同时访问时,会开启多线程,但是,这时有可能发生异常。
说明接口在多线程访问中不是很稳定,这时就要利用多线程的Debug调试。
以下是一个小Demo来演示多线程的Debug调试
public class LockDemoReetrantLock {
private int i=0;
private ReentrantLock reentrantLock=new ReentrantLock();
public void inCreate(){
断点 reentrantLock.lock();
try{
i++;
}finally {
reentrantLock.unlock();//注意:一般的释放锁的操作都放到finally中,
// 多线程可能会出错而停止运行,如果不释放锁其他线程都不会拿到该锁
}
}
public static void main(String[] args){
ReentrantLock lock = new ReentrantLock();
lock.lock();
LockDemoReetrantLock lockDemoReetrantLock = new LockDemoReetrantLock();
for (int i=0;i<3;i++){
new Thread(()->{
lockDemoReetrantLock.inCreate();
}).start();
}
}
}
开始刚一执行此时i=2
接着下一步下一步,程序直接跳出 看不到ReentrantLock的排队操作,
再次运行
在进行一次调试此时i=1
同样看不到排队操作,不是我们想要的结果!!
在断点调试的断点上右击实现设置(Mac版)
一运行Debug 其它两个线程就已经启动了,中有一个线程能够停止到这个断点
改为Thread之后---->makeDefault---->done
此时就Ok了
F8
接下来我们看第二个线程是否获得锁
点入该线程(012线程顺序是随机的)
F8显示未挂起的线程不可用 该线程没能获取到该锁(同理Thread2也不能获取该锁)
线程1和2 wait 线程0和主线程running
线程1和2都在等待资源
接下来看ReetrantLock 的执行过程
重新启动
此时3个线程都停留在这
此时跳入inCreat方法
再条进到lock方法中去 进入到非公平锁的实现
F8首先执行CAS
其他线程就不会执行
此时由于是线程0先执行的,我们再开一下线程1(012执行顺序是随机的这里假定0先执行)
接下来看线程1
之后执行acquire方法
再跳
跳进去
此时addWaiter执行完毕
接着执行acquireQueued方法
同理线程2也这样
执行tryRelease方法
tryRelease方法执行成功
执行完成之后就会唤醒其他线程
该线程执行完毕
接着查看其他线程(1,2)