解决logback不打印e.printStackTrace(),并分析能够造成死锁的问题

举报
小小张自由--张有博 发表于 2022/03/30 23:30:40 2022/03/30
【摘要】 解决logback不打印e.printStackTrace(),并分析能够造成死锁的问题

解决logback不打印e.printStackTrace(),创建代理类

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.io.PrintStream;
import java.util.function.Consumer;

/**
 * 解决logback不处理e.printStackTrace()的问题
 *
 * @author Promsing(张有博)
 * @version 1.0.0
 * @since 2022/3/21 - 11:15
 */
@Configuration
public class LogSystemProxy {

    private final static Logger log = LoggerFactory.getLogger("system.log");

    @PostConstruct
    public void initProxy(){
        log.debug("LogSystemProxy init .....");
        System.setOut(getLoggerProxy(StdType.OUT));
        System.setErr(getLoggerProxy(StdType.ERR));
    }


    private enum StdType{
        OUT(System.out, log::info),
        ERR(System.err, log::error),
        ;
        PrintStream stream;
        Consumer<String> consumer;
        StdType(PrintStream stream,Consumer<String> consumer){
            this.stream = stream;
            this.consumer = consumer;
        }
    }

    private PrintStream getLoggerProxy(StdType stdType){
        return new PrintStream(stdType.stream){
            @Override
            public void print(String s) {
                stdType.stream.print(s);
                stdType.consumer.accept(s);
            }
        };
    }
}

这个类有很大问题,容易造成进程死锁,系统假死。

死锁的概念

死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。

1648382618740-2d257949-79a5-4b9f-b4c2-d7e944037565.png

死锁产生的条件

虽然进程在运行过程中,可能发生死锁,但死锁的发生也必须具备一定的条件,死锁的发生必须具备以下四个必要条件 [2]

1)互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。

2)请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。

3)不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。

4)环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。

打印日志假死现象:

控制台和日志文件都会有日志

1648384422336-3a6342ee-8052-4e80-a2a8-2c1abb3e426e.png

方法调用流程

1648387150853-cca60354-fc8c-4393-bb2c-0827cfb5691b.png

1648387175493-df53c35f-49e2-421c-b766-f797bafd83db.png

代码执行过程

1648387682106-be3f0de7-6a92-43b3-9206-e29831e6bb9f.png

1648388781656-15b148ca-65b6-4cea-94df-e4e63444a191.png

1648389739463-fc58f1dc-1bb3-4e16-8dbd-1dbdb9b8146e.png

1648389874091-9ea77180-580b-4c11-aed7-5fda8257e571.png

1648390048781-d86c2861-ef28-4dec-9691-f547b669a947.png

仔细分析了以上代码的调用流程,当并发上来之后,确实可以产生死锁,造成jar包假死。



【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。