关于jvm范围的属性和多线程的问题

时间:2011-05-15 09:08:35

标签: java multithreading security concurrency java-ee


我需要使用(目前)一些java apis -unfortunatelly-只能通过jvm属性“配置”。
我知道这会影响多线程,因为修改属性的一个线程可能会影响其他运行 所以我想在同步方法中做到这一点,例如

public static sychronized void someMethod(){
   Security.setProperty("responderURL",IP);
   //do code here
}

似乎没关系,但我想知道是否有任何陷阱,以及这些案件是否有任何设计模式?

由于

4 个答案:

答案 0 :(得分:4)

当您创建同步静态方法时,它会在该方法所在的类上进行同步。这意味着该类中只能有一个方法一次运行。如果这可以解决你的问题,那就完美了。

但是,如果JVM中的任何其他方法修改了该类之外的那些属性,或者修改了在类上同步的方法之外的那些属性,那么您的努力将不会产生任何影响。

答案 1 :(得分:2)

您不需要同步,System.setProperty已经是同步方法,虽然System.getProperty未同步,但属性类扩展了HashTable,它具有同步方法来访问其键值对。因此,你不需要担心同步问题..

编辑:

关于我的回答的一些澄清;

1.如果您的方法应该作为一个原子单位工作,它应该是同步的,例如;

    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");
    }

您应该同步您的方法,因为当线程1检查responderURL属性时,线程2可以设置此属性。

2.但是如果你的方法只设置responderURL属性,并且它的功能不依赖于respondrURL属性当前值,你就不需要同步你的方法..

  public static  void someMethod(){
            System.setProperty("responderURL",IP);
           //do code here
           //some code
           URL url  = new URL(IP,8080,"test.txt");
      }

答案 2 :(得分:0)

使用synchronized将无法帮助您。 {1}在您的示例中唯一做的就是确保两个线程不能同时调用您的同步方法

synchronized

完全相同
public class Foo {
  public static synchronized void bar() {
       //...    
  }
}

即。只有可以看到public class Foo { public static void bar() { synchronized (Foo.class) { //... } } } 并在其上进行同步的代码才会受到同步的影响。由于您调用的任何库中的代码显然不了解Foo.class,因此同步它不会产生任何影响。

如果您希望保证在任何可能读取值的代码运行之前设置这些系统属性,那么最安全的方法是将它们作为-D参数传递给java命令它启动JVM,例如 Foo.class

下一个最好的方法是,正如您所做的那样,在VM启动的早期名为的某种方法中设置属性。但是,如果可能的话,最好使用命令行参数来执行此操作,原因如下:如果在您正在使用的库中的静态{}块中读取任何此类属性,那些块可能在代码执行之前运行,因为Java的字节码验证程序可能会导致在代码执行任何调用它们之前初始化这些类(您可以通过将java -DresponderURL=http://foo.bar传递给Java命令来避免这种情况,但如果您可以这样做,那么您不管怎样,也可以在那里设置系统属性。)

答案 3 :(得分:0)

如果这是一次性配置,则在静态初始化块内执行此操作。如果没有,你所拥有的是经典的读写器问题。 java.util.concurrent javadocs有一些很好的样本解决方案。