开发者

Question on jvm-wide properties and multithreading

I need to use (at the moment) some java apis that -unfortunatelly- can be "configured" only via jvm properties.

I understand that this can affect multithreading, since it can be the case that one thread modifying the properties can affect the others runnin开发者_开发技巧g.

So I thought to do this inside a synchronized method e.g.

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.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜