开发者

Why is TimeZone.getTimeZone(id) synchronized, and why this isn't documented?

java.util.TimeZone.getTimeZone(id) is a method to obtain a timezone bas开发者_StackOverflow社区ed on an id. While I was using the class I opened it with a decompiler and noticed that it is synchronized. And since it is static, this means that no two threads can invoke the method at the same time. This could be very painful if multiple threads (in a web application for example) are often getting timezones. Why does it have to be synchronized?

Then I realized that the documentation doesn't say anything about synchronization. So, my decompiler could be wrong. Then I opened the source, and it is synchronized. Why this is not documented? I'm aware that javadoc doesn't include the synchronized keyword, but it could have been mentioned.

The solution, of course, is to use joda-time DateTimeZone


The method can end up actually creating a TimeZone (follow the code down) and adding it to a Map. I'm guessing that everyone considered that this isn't a method you should be calling often and took the easy way out.

I'd have difficulty coming up with a legitimate case where this synchronized would be contended. Uncontended synchronized (even in really high-performance cases, which is something I work on quite often) is cheap as chips.

To get contention, you need not just many threads, but many threads that are hitting this particular block of code at the same time. If you were really having a problem with that in this case, you could easily keep your own cache in a ConcurrentHashMap, or in an entirely unlocked structure.

As to why it's not documented - synchronization is a property of the implementation. You'd be welcome to implement an alternative library that doesn't do this synchronization. The JDK docs are documenting the Java libraries, not (for the most part) Sunacle's implementation thereof.


We saw this same issue, blocking threads in TimeZone. It looks like a regression introduced in Nov 2011, see http://hg.openjdk.java.net/jdk6/jdk6/jdk/annotate/dd8956e41b89/src/share/classes/java/util/TimeZone.java. Previously TimeZone used InheritableThreadLocal for the Map. TimeZone functions are now controlled by SecurityManager (with a synchronized HashMap under the AppContext class). The following functions are affected: Date.normalize (called by toString, getTime, and a bunch of deprecated methods), Calendar.getInstance (except for the one where Locale is a parameter). http://coffeedriven.org/2012/10/14/be-carefull-with-calendar-getinstance-and-timezone-gettimezone also refers to the same issue.

The stack trace (JDK6.45) from VisualVM:

java.lang.Thread.State: BLOCKED (on object monitor)
at sun.awt.AppContext.get(AppContext.java:572)
- waiting to lock <0x0000000705490070> (a java.util.HashMap)
at sun.awt.AppContext$6.get(AppContext.java:774)
at java.util.TimeZone.getDefaultInAppContext(TimeZone.java:637)
at java.util.TimeZone.getDefaultRef(TimeZone.java:523)
at java.util.Date.normalize(Date.java:1176)
at java.util.Date.toString(Date.java:1010)

I intend to file a bug report with Oracle on this, I just need to recreate a small test case to clearly demonstrate the problem, with a suggested code fix.

The JodaTime documentation states: Joda-Time also allocates very few temporary objects during operations, and performs almost no thread synchronization. In systems that are heavily multi-threaded or use a lot of memory, Calendar, SimpleDateFormat, and TimeZone can become bottlenecks. When the Joda-Time classes are used instead, the bottlenecks go away.

The workaround is to either use JodaTime library, or to patch the JDK TimeZone class, or wait for Oracle to remediate the issue.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜