Refactoring and Concurrency - overview
The Refactoring and Concurrency project aims to discover novel ways to apply refactoring techniques to concurrent programs. The scope of the project includes both (1) developing refactorings that can improve performance of concurrent programs and (2) devising enhancements of traditional refactorings to ensure they can be applied to concurrent code.
Refactorings to Improve Concurrency
We have developed a tool called Reentrancer that refactors existing single-threaded Java programs to make them reentrant. A program is reentrant if distinct executions of the program on distinct inputs cannot affect each other. Reentrancy is a useful property since it enables parallel program executions on distinct inputs without additional concurrency control. Unfortunately, many existing Java programs are not reentrant since they rely on mutable global state. Reentrancer replaces such global state with thread-local state, yielding reentrancy assuming each execution occurs in a fresh thread. For more details, see our ESEC/FSE 2009 paper.
More recently, we developed Relocker, a tool that aids in refactoring to and from the locking constructs in the java.util.concurrent.locks package. The performance of the different Java locking constructs can vary widely based on the underlying JVM, application load, etc., and hence experimentation is necessary to decide which construct is best. However, translating code to use a different locking construct is a non-trivial process that can lead to subtle concurrency bugs if done incorrectly. By automating much of this transformation process, Relocker eases the process of discovering which locking constructs are best for a program. For details, see our ICSE 2011 paper. Also, you can download a prototype Eclipse plug-in here.
Applying Existing Refactorings to Concurrent Code
Automated refactorings as implemented in modern IDEs for Java usually make no special provisions for concurrent code. Thus, refactored programs may exhibit unexpected new concurrent behaviors. We have analyzed the types of such behavioral changes caused by current refactoring engines and developed techniques to make them behavior-preserving, ranging from simple techniques to deal with concurrency-related language constructs to a framework that computes and tracks synchronization dependencies. By basing our development directly on the Java Memory Model, we have proved precise correctness results about refactoring concurrent programs. We showed that a broad range of refactorings are not influenced by concurrency at all, whereas other important refactorings can be made behavior-preserving for correctly synchronized programs by using our framework. Experience with a prototype implementation showed that our techniques are easy to implement and require only minimal changes to existing refactoring engines. For more details, see our ECOOP 2010 paper.
- Jan Wloka