Java SE 11 : Moving Java Forward – Part 3 : Thread Safe compilation checking
This series of articles presents how, in my opinion, the java language should evolve to remain a top-choice language. It also presents some features, sometimes already existing in other languages, which I love but that cannot (or should never) be part of Java, for reasons that I will explain. I would really love to transform some of those ideas into JSRs one day.
Thread Safe compilation checking: What is it?
Thread Safe Compilation-Checking is the ability to check that your program will not have issues due to multi-threading. As far as I know, no programming language provides this functionality (If you know one, please let me know!).
What is the problem?
Developing a program that runs in several threads is easy, developing something that won't have any weird bugs due to that thread mechanism is far more difficult.
Why is concurrent programming is hard?
Because to make a good multi-thread application, you have to be very careful and know the Java language and the API perfectly: avoid deadlocks, know when to use the volatile keyword, know what is (or not) thread-safe.
The other difficulty is that testing/debugging a multi-thread application is very hard. You can spend several days wondering why in your huge database you have this row with a weird date value... To finally realize that your co-developer (of course not you, since you are a java guru ;) ) has used a SimpleDateFormat object shared by several threads... (BTW, if you didn't know: yes, SimpleDateFormat is not thread safe.)
What is the solution?
The solution is thread safe compilation checking! It would make the development so much easier if you had a warning telling you "At line 36: Not Thread Safe code. Usage of a non thread safe method SimpleDateFormat.format.”
Why it is impossible
Usage of non-thread-safe APIs
At the moment, the only way to know if the libraries/APIs you are using are thread-safe is to read Javadoc or the source code so the compiler has no way to know if what you call is, or is not, thread-safe. By transitivity, if you are not using any kind of synchronization mechanism, it has no way to know if your code is thread-safe or not since you are using those libraries.
One solution to this issue could be to create an @ThreadSafe annotation to annotate classes and methods. That way, any element annotated with @ThreadSafe would be considered as thread-safe by the compiler. Of course, all the APIs you use need to be annotated correctly... Apart from the compilation-checking thing, I think that such an annotation would be great to make the APIs clearer.
The Reflection API
The Reflection API is another issue. Since the execution flow is determined during the run-time, the compiler cannot know what methods will be called and so cannot determine if what is going to be executed is thread-safe.
The compiler needs to know the context
The compiler has no way to know if what you are developing is going to be executed in a thread safe environment or not. For example if you are developing a bean that is going to be injected everywhere by your favorite CDI framework, the compiler cannot know it.
In other words, the compiler knows less than you and so cannot determine if what you are programming needs to be thread safe or not. Let's say you are programming a controller for your J2EE application; If you don't annotate your controller with the hypothetical @ThreadSafe annotation, the compiler won't ever complain. The problem is that your controller has to be thread-safe! If you don't annotate correctly with @ThreadSafe what had to be thread safe, you will have issues...
The different locking mechanisms
If the only way to synchronize your threads was the synchronized keyword, it would be easier for the compiler to determine if a piece of code can be run concurrently or not. Unfortunately that isn't the case! You have several ways to ensure that your code will be executed only in the right context (ReentrantLock, ReadWriteLock, manual locks using a file, a socket, an object, a counter etc...). To me, this is why the "thread-safe compilation checking" is impossible to implement. If the compiler is not able to spot the synchronization mechanism, it can't know anything about thread safety!
Thread-safe compilation checking would definitely be a killer feature. But to me, it is impossible to implement, even partially, and that's probably why I have never seen this feature in any languages.
If you have any ideas of a solution or if you know any language that does it, even partially, let me know!