【问题标题】:is the below static utility method Threadsafe是下面的静态实用方法 Threadsafe
【发布时间】:2013-03-28 16:29:53
【问题描述】:

我正在编写一个静态实用程序方法。我知道方法 isEmpty() , isNew() 是线程安全的。在 getTotal(...) 方法中,我使用 StringBuilder 作为参数 alomg 与 String 和 int.StringBuilder 是可变的。 getTotal() 是线程安全的。如果是这样,请解释为什么即使 StringBuilder 是 mutable 也是如此。 但我不确定 getCharge() 是否是线程安全的,因为它调用方法 getTotal()。 有人可以判断它是否是线程安全的

public class NewStringUtils {

    public static boolean  isEmpty(String s){
        return (s == null || s.trim().length()==0);
    }

    public static boolean isNew(String code){
        return( "1009".equals(code) || "1008".equals(code) );
    }
    //StringBuilder is  mutable  -- is the below method threadsafe 
    public static int getTotal(StringBuilder sb,String oldCode ,int a, int b){
        //Is it Threadsafe or not .If so  just bcz every thread invoking this method will have its own copy and other threads can't see its value ?? 
        int k =0;
        if("1011".equals(oldCode) && "1021".equals(sb.toString()) {
            k = a+b;
        }
        return k;
    }
    // is the below method threadsafe 
    public static  int getCharge(String code,String oldCode,int charge1,int charge2){
        int total =0;
        StringBuilder sb = new StringBuilder("1021");
        if(!NewStringUtils.isEmpty(code)){

            if(NewStringUtils.isNew(code)){
                //here invoking a static method which has StringBuilder(Mutable) as a         parameter
                total  = NewStringUtils.getTotal(sb,oldCode,charge1,charge2);
            }
        }

        return total;
     }
}

【问题讨论】:

  • 你有什么理由怀疑它不是线程安全的吗?

标签: java multithreading


【解决方案1】:

是的。您没有使用任何非方法范围的字段/变量,并且方法的所有参数都是不可变的,因此它是线程安全的。

不使用任何非方法范围变量的方法中唯一的线程安全风险是参数是否可变,因此可能被另一个线程修改。由于原语和String 是不可变的,所以你很好。

编辑:发表评论:

这个怎么样:如果一个方法(静态或其他)只使用 方法范围的变量,只有不可变参数并且只有 调用其他线程安全的方法,那么它必须是线程安全的

【讨论】:

  • String 是不可变的,但 int 是可变的对。所以你还认为它是线程安全的
  • 原语是不可变的(没有myInt.set(..)这样的东西)。此外,我的定义原语按值传递给方法(因为不可能引用原语)。
  • 所以根据你的说法,如果我有一个像 StringBuffer 这样的可变对象作为 getTotal() 中的参数,它就会变成非线程安全的 public static int getTotal(StringBuffer sb, String oldCode ,int a, int b){ int k =0; if("1011".equals(oldCode)) { k = a+b; } 返回 k; }
  • 正确。例如,如果getCharge 采用StringBuffer,则参数的值可能会在对isEmptyisNew 的调用之间发生变化
  • ok 。如果静态方法不使用状态信息,那么在静态方法中将原语和不可变对象作为参数始终是线程安全的。如果我使用不可变对象作为参数会出现问题
【解决方案2】:

您的静态方法在调用之间没有任何状态。通过参数传递的所有状态......所以它的线程安全。

【讨论】:

    【解决方案3】:

    所有变量都是局部变量,线程之间没有共享变量(静态变量,因为它是静态方法),传递的引用要么是原语,要么是不可变类的实例。因此,它是线程安全的。

    【讨论】:

      【解决方案4】:

      是的,是的。 ints 按值传递。 Strings 是方法的参数。您没有使用方法外部的任何字段。

      编辑

      如果您想使用StringBuilder 而不是String,则需要在StringBuilder 对象上进行同步。

      public someMethod(StringBuilder sb, ...) {
          synchronized(sb) {
      
              //this will make sb thread safe.
              //but do this everywhere you access this StringBuilder Object.
      
          }
      }
      

      【讨论】:

      • 那么如果我将方法 def 更改为 public static int getTotal(StringBuffer sb, String oldCode ,int a, int b){ 由于 StringBuffer 是可变的,它仍然是线程安全的 public static int getTotal (StringBuffer sb, String oldCode ,int a, int b){ int k =0; if(sb!=null && NewStringUtils.isEmpty(sb.toString)){ if("1020".equals(sb.toString){ if("1011".equals(oldCode)) { k = a+b; } } } 返回 k; }
      • 那么,不。您需要在 StringBuffer 对象上进行同步。
      • 谢谢。所以我必须在 getTotal(StringBuffer sb,String code,int ch1,int ch2) 方法中获取类级锁(这是一个静态方法)以使其成为线程安全的。在方法内部同步(this.class){ //然后对字符串缓冲区进行更改 }
      • 没有。您不想在类上同步,而是在 StringBuffer 对象中同步。在你使用这个 StringBuffer 的地方,你需要一个同步块。
      • 对不起,我没听懂。我想我应该得到类级别同步(NewUtils.class){并在 StringBuffer 上采取行动}。纠正我我错了
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-25
      • 2012-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-25
      相关资源
      最近更新 更多