kuyyi
kuyyi

Reputation: 29

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

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?

Upvotes: 2

Views: 324

Answers (1)

Stephen C
Stephen C

Reputation: 719596

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.

Upvotes: 1

Related Questions