Question on jvm-wide properties and multithreading
public static sychronized void someMethod(){
Security.setProperty("responderURL",IP);
//do code here
}
It seems it is ok, but I was wondering if there any pitfalls on this and whether there is any kind of design pattern for cases like these?
Thanks
When you create a synchronized static method, it synchronizes on the class that the method is in. This means that only one method in that class will be able to run at a time. If that solves your problem, then perfect.
However, if any other method in the JVM modifies those properties outside of that class or outside of a method that's synchronized on the class, then your efforts won't have any effect.
You dont need to synchronize , System.setProperty
is already synchronized method, and although System.getProperty
is not synchronized, Properties class extends HashTable which has syncronized method to access its key-value pairs.As a result, you dont need to do worry about synchronizing issues..
EDIT :
Some clarifications about my answer ;
1.If your method should work as an atomic unit, it should be synchronized , such as ;
public static sychronized void someMethod(){
if (System.getProperty("responderURL")==null)
System.setProperty("responderURL",IP);
//do code here
//some code
URL url = new URL(System.getProperty("responderURL"),8080,"test.txt");
}
You should synchronized your method, because while Thread 1 is checking responderURL property , Thread 2 could set this property.
2.But if your method sets only responderURL property, and its functionality does not depend respondrURL property current value, you dont need to synchronize your method..
public static void someMethod(){
System.setProperty("responderURL",IP);
//do code here
//some code
URL url = new URL(IP,8080,"test.txt");
}
Using synchronized won't help you here. The only thing synchronized
does in your example is ensure that two threads cannot call your synchronized method simultaneously.
public class Foo {
public static synchronized void bar() {
//...
}
}
is exactly the same as
public class Foo {
public static void bar() {
synchronized (Foo.class) {
//...
}
}
}
i.e. only code that can see Foo.class
and synchronizes on it will be affected by your synchronization. Since code in whatever libraries you are calling obviously does not know about Foo.class, synchronizing on it will not have any effect.
If you want to guarantee that these system properties are set before any code runs which might read the values can possibly run, the most bulletproof way is to pass them as -D arguments to the java command which starts the JVM, e.g.
java -DresponderURL=http://foo.bar
.
The next best approach is, as you are doing, set the properties in some method called early in VM startup. It is always preferable to do it with command-line arguments if possible, though, for this reason: If any such properties are read in static{} blocks in the libraries you're using, those blocks may run before your code does, because Java's bytecode verifier may cause those classes to be initialized before your code does anything that calls them (you can avoid this by passing -Xverify:none
to the Java command, but if you can do that, you might as well just set the system properties there anyway).
If this is one time configuration, you do this inside a static initialization block. If not, what you have is the classic reader-writer problem. The java.util.concurrent
javadocs have some good sample solutions.
精彩评论