Java programs perform many synchronization operations on data structures. S
ome of these synchronizations are unnecessary; in particular, if an object
is reachable only by a single thread, concurrent access is impossible and n
o synchronization is needed. We describe an interprocedural, flow- and cont
ext-insensitive data-flow analysis that finds such situations. A global opt
imizing transformation then eliminates synchronizations on these objects. F
or every program in our suite of ten Java benchmarks consisting of SPECjvm9
8 and others, our system optimizes over 90% of the alias sets containing at
least one synchronized object. As a result, the dynamic frequency of synch
ronizations is reduced by up to 99%. For two benchmarks that perform synchr
onizations very frequently, this optimization leads to speedups of 36% and
20%.