美文网首页
slf4j初始化线程安全历险记

slf4j初始化线程安全历险记

作者: eclipse2x | 来源:发表于2016-08-30 16:50 被阅读0次

    最近发现项目中的日志用得不大规范,于是准备做些改造,在我们项目中用的是 slf4j1.5.10 的版本,顺便看了下 slf4j 的源码,看到 LoggerFactory 初始化的逻辑如下

      public static ILoggerFactory getILoggerFactory() {
        if (INITIALIZATION_STATE == UNINITIALIZED) {
          INITIALIZATION_STATE = ONGOING_INITILIZATION;
          performInitialization();
        }
        switch (INITIALIZATION_STATE) {
        case SUCCESSFUL_INITILIZATION:
          return getSingleton().getLoggerFactory();
        case FAILED_INITILIZATION:
          throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);
        case ONGOING_INITILIZATION:
          // support re-entrant behavior.
          // See also http://bugzilla.slf4j.org/show_bug.cgi?id=106
          return TEMP_FACTORY;
        }
        throw new IllegalStateException("Unreachable code");
      }
    

    有发现什么问题吗?再看看 INITIALIZATION_STATE 这个变量是怎么声明的,如下

      static int INITIALIZATION_STATE = UNINITIALIZED;
    

    现在很明确了,如果在多线程环境下,多个线程调用 LoggerFactory.getLogger() 方法的时候初始化会出现问题,这简直有点颠覆世界观,说好的大神代码呢?怀着极度怀疑自己的心情翻看了最新的 slf4j1.7.21 代码,看到初始化逻辑如下:

         public static ILoggerFactory getILoggerFactory() {
            if (INITIALIZATION_STATE == UNINITIALIZED) {
                synchronized (LoggerFactory.class) {
                    if (INITIALIZATION_STATE == UNINITIALIZED) {
                        INITIALIZATION_STATE = ONGOING_INITIALIZATION;
                        performInitialization();
                    }
                }
            }
            switch (INITIALIZATION_STATE) {
            case SUCCESSFUL_INITIALIZATION:
                return StaticLoggerBinder.getSingleton().getLoggerFactory();
            case NOP_FALLBACK_INITIALIZATION:
                return NOP_FALLBACK_FACTORY;
            case FAILED_INITIALIZATION:
                throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);
            case ONGOING_INITIALIZATION:
                // support re-entrant behavior.
                // See also http://jira.qos.ch/browse/SLF4J-97
                return SUBST_FACTORY;
            }
            throw new IllegalStateException("Unreachable code");
        }
    

    再看看 INITIALIZATION_STATE 变量的声明

            static volatile int INITIALIZATION_STATE = UNINITIALIZED;
    

    顿时泪流满面,这才像传说中的大神代码啊

    相关文章

      网友评论

          本文标题:slf4j初始化线程安全历险记

          本文链接:https://www.haomeiwen.com/subject/ddzfettx.html