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;
}
以上代码是jdk源代码
jdk公司version:1.8.0_144
异常堆栈不应该是线程私有的吗?为什么需要同步控制?
1条答案
按热度按时间kokeuurv1#
为什么下面的方法
Throwable
班级需要同步吗?因为正常的原因。可能会有两个线程同时执行某个操作来触发这些调用中的任何一个。如果他们不是
synchronized
那可能会导致竞争状况或内存异常。(请注意
stacktrace
或者backtrace
是volatile
因此,如果代码是从多个线程测试和/或分配的,则有些线程可能会看到过时的值。)现在,对所有可能的代码路径进行深入分析可能会发现,该代码在不声明这些方法的情况下是线程安全的
synchronized
. 但如果是我写的代码,我可能会用synchronized
无论如何,因为:使用起来很安全
synchronized
这里,还有相对于捕获异常的堆栈跟踪时发生的所有其他事情,互斥(可能是不必要的)的开销将很小,并且
例外情况应该很少发生。。。除非程序不正确地使用异常。
如果获取异常的stacktrace不是线程安全的,那么这是不可接受的。如果堆栈跟踪不可靠,那么调试java就完全是“废话”。在这种情况下,即使规范(javadoc)对此保持沉默,代码也必须是线程安全的。