2
private StackTraceElement[] stackTrace = UNASSIGNED_STACK;
private transient Object backtrace;

private synchronized StackTraceElement[] getOurStackTrace() {
    // Initialize stack trace field with information from
    // backtrace if this is the first call to this method
    if (stackTrace == UNASSIGNED_STACK ||
        (stackTrace == null && backtrace != null) /* Out of protocol state */) {
        int depth = getStackTraceDepth();
        stackTrace = new StackTraceElement[depth];
        for (int i=0; i < depth; i++)
            stackTrace[i] = getStackTraceElement(i);
    } else if (stackTrace == null) {
        return UNASSIGNED_STACK;
    }
    return stackTrace;
}

public synchronized Throwable fillInStackTrace() {
    if (stackTrace != null ||
        backtrace != null /* Out of protocol state */ ) {
        fillInStackTrace(0);
        stackTrace = UNASSIGNED_STACK;
    }
    return this;
}

public synchronized Throwable fillInStackTrace() {
    if (stackTrace != null ||
        backtrace != null /* Out of protocol state */ ) {
        fillInStackTrace(0);
        stackTrace = UNASSIGNED_STACK;
    }
    return this;
}

The above code is the jdk source code

jdk version:1.8.0_144

Shouldn't the exception stack be private to the thread? Why do you need synchronization control?

kuyyi
  • 29
  • 3

1 Answers1

1

Why do the following methods of the Throwable class need to be synchronized?

For the normal reasons. There could be situations where two threads simultaneously do something that trigger either of these calls. If they are not synchronized then that could result in a race condition or a memory anomaly.

(Notice that neither stacktrace or backtrace are volatile so if the code tested and/or assigned them from multiple threads, there is a risk of some threads seeing stale values.)

Now a deep analysis of all of the possible code paths might reveal that this code would be thread-safe without declaring those methods synchronized. But if it was me writing the code, I would probably used synchronized anyway because:

  • it is clearly safe to use synchronized here, and
  • the overheads of a (possibly unnecessary) mutex will be tiny relative to all of the other things that are going on when the stack trace for an exception is captured, and
  • exceptions should be infrequent ... unless the program is using exceptions incorrectly.

It would be unacceptable if getting the stacktrace of an exception was not thread-safe. Debugging Java would be a total "crap shoot" if stack traces were unreliable. This is one of those cases where the code must be thread-safe even if the spec (the javadoc) is silent about it.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • According to my understanding, if it is confirmed that it is thread-safe, then synchronization is obviously redundant. If it is not thread-safe that synchronization needs to be controlled, then I consider that if synchronization is removed, under what circumstances will cause problems, this is what I am now Doubts and puzzles – kuyyi Jan 10 '21 at 06:40
  • Well, your understanding is different to mine. According to my understanding, unless you can **prove** that the code is thread-safe (in all situations) without `synchronized` you should **not** remove the synchronization. Can you prove that? Having "doubts" is OK, but we don't change code just because someone has "doubts". "Doubts" are not proof. – Stephen C Jan 10 '21 at 06:43
  • (I should add that by "we", I meant responsible programmers ... generally. I don't claim to speak for the Java development team. I don't claim to speak for anyone other than myself ...) – Stephen C Jan 10 '21 at 07:08