2021-04-26 模拟死锁用jstack查看

学习总结

  • 《Linux Shell 脚本攻略》这本书学习到了第三章(83/268)
  • 开始学习《JAVA并发编程的艺术》这本书
  • jstack查看死锁的情况
  • 大概了解了volatile在CPU指令集的处理逻辑

明日安排

  • 继续阅读《JAVA并发编程的艺术》这本书

笔记内容

《JAVA并发编程的艺术》

  • 如何减少上下文切换?
    • 无锁并发编程。多线程竞争锁时,会引起上下文切换,所以多线程处理数据时,可以用一些办法来避免使用锁,如将数据的ID按照Hash算法取模分段,不同的线程处理不同段的数据。
    • CAS算法。Java的Atomic包使用CAS算法来更新数据,而不需要加锁。
    • 使用最少线程。避免创建不需要的线程,比如任务很少,但是创建了很多线程来处理,这样会造成大量县城都处于等待状态。

实战

jstack命令查看进程中是否存在大量WAITING状态的进程,
由此判断线程池大小是否合适。通过减少空闲线程数量减少上下文切换次数

模拟死锁

模拟代码如下


public class 模拟死锁 {
    
    
    private final static String A = "A";
    private final static String B = "B";

    @Test
    public void test() throws InterruptedException {
    
    
        Thread threadA = new Thread(()->{
    
    
            synchronized(A){
    
    
                try {
    
    
                    Thread.sleep(100);
                    synchronized (B){
    
    
                        System.out.println("Get");
                    }
                } catch (InterruptedException e) {
    
     }
            }
        });
        Thread threadB = new Thread(()->{
    
    
            synchronized(B){
    
    
                try {
    
    
                    Thread.sleep(100);
                    synchronized (A){
    
    
                        System.out.println("Get");
                    }
                } catch (InterruptedException e) {
    
     }
            }
        });
        threadA.start();
        threadB.start();
        threadA.join();
        System.out.println("END");
    }
}

使用jstack,输出的结果里已经有了关于死锁的提示信息

virde@virde:~$ jps -l
76342 org.jetbrains.jps.cmdline.Launcher
76424 jdk.jcmd/sun.tools.jps.Jps
67466 com.intellij.idea.Main
76364 com.intellij.rt.junit.JUnitStarter
76126 org.jetbrains.idea.maven.server.RemoteMavenServer36
67934 org.jetbrains.idea.maven.server.RemoteMavenServer36
virde@virde:~$ jstack 76364
2021-04-26 15:43:08
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.181-b13 mixed mode):
Java stack information for the threads listed above:
……
……

===================================================
"Thread-1":
	at 多线程.模拟死锁.lambda$test$1(模拟死锁.java:26)
	- waiting to lock <0x000000076d73f678> (a java.lang.String)
	- locked <0x000000076d73f6a8> (a java.lang.String)
	at 多线程.模拟死锁$$Lambda$2/380894366.run(Unknown Source)
	at java.lang.Thread.run(Thread.java:748)
"Thread-0":
	at 多线程.模拟死锁.lambda$test$0(模拟死锁.java:16)
	- waiting to lock <0x000000076d73f6a8> (a java.lang.String)
	- locked <0x000000076d73f678> (a java.lang.String)
	at 多线程.模拟死锁$$Lambda$1/1068824137.run(Unknown Source)
	at java.lang.Thread.run(Thread.java:748)

Found 1 deadlock.

virde@virde:~$ 

避免死锁的几个常见方法

  • 避免一个线程同时获取多个锁
  • 避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源。
  • 尝试使用定时锁,使用lock.tryLock(timeout)来替代使用内部锁机制
  • 对于数据库锁,加锁和解锁必须在一个数据库连接里,否则会出现解锁失败的情况

IDEA lombok 报错解决记录

项目中使用了lombok,mvn构建的时候没报错,但是运行时报错。
get,set方法找不到。

百度了解到,maven版本与idea lombok 版本不一致可能会报错。
在根目录的pom.xml中将lombok更新至最新版本。还是报错。

查看项目中External Libraries目录中的文件发现,
存在两个版本的lombok

Maven:org.projectlombok:lombok:1.18.10
Maven:org.projectlombok:lombok:1.18.20

我明明引入了最新版本1.18.20,那么1.18.10版本哪来的?
再次排查pom.xml文件,原来是子项目的pom.xml引入了低版本。

子项目去掉引用,问题解决

参考:idea lombok简介及报红、报错解决办法

猜你喜欢

转载自blog.csdn.net/kaka_buka/article/details/116170678