这个静态方法线程是安全的还是需要同步的

时间:2016-02-05 19:11:28

标签: java multithreading concurrency thread-safety

我有一个实用程序类,它有一个静态方法来修改输入数组列表的值。调用者调用此静态方法。调用者用于处理Web服务请求。对于每个请求(每个线程),调用者创建一个新的ArrayList并调用静态方法。

e

这是克隆标准的方式:

public class Caller{

   public void callingMethod(){

     //Get Cloned criteria clones a preset search criteria that has place holders for values and returns a new ArrayList of the original criteria. Not included code for the clone
     ArrayList<Properties> clonedCriteria = getClonedCriteria();

     CriteriaUpdater.update(clonedCriteria , "key1", "old_value1", "key1_new_value");
     CriteriaUpdater.update(clonedCriteria , "key2", "old_value2", "key2_new_value");

    //do something after the this call with the modified criteria arraylist
   }

}

public class CriteriaUpdater
{
    //updates the criteria, in the form of array of property objects, by replacing the token with the new value passed in
    public static void update(ArrayList<Properties> criteria, String key, String token, String newValue)
    {
        for (Properties sc: criteria)
        {
            String oldValue = sc.getProperty(key);
            if ((oldValue != null) && (oldValue.equals(token))) 
                sc.setProperty(key, newValue);
        }
    }
}

鉴于上述定义,通过不同步静态方法,它是否仍能正确处理并发方法调用。我的理解是我必须同步这个方法的并发性,但想确认一下。 我理解每个线程都有自己的堆栈,但是对于静态方法,它对所有线程都是通用的 - 所以在这种情况下,如果我们不同步它会不会导致问题? 感谢建议和任何更正。

由于

3 个答案:

答案 0 :(得分:1)

您遇到竞争条件问题。至少底层的mydatabase=# alter table mytable add column newcolumn character varying(50); ERROR: No peer nodes or peer node count unknown, cannot acquire DDL lock HINT: BDR is probably still starting up, wait a while mydatabase=# 数据结构永远不会被破坏,但它可能具有不正确的值。特别是,本节中可以包含任意数量的线程,这意味着最终值可以是任何线程中的任何内容。

Properties

我假设您的列表永远不会被更改,但如果是,则必须有 String oldValue = sc.getProperty(key); if ((oldValue != null) && (oldValue.equals(token))) sc.setProperty(key, newValue); 。你可以锁定类,但锁定你正在改变的集合可能是一个更好的选择。

答案 1 :(得分:0)

你是正确的,因为每个线程都有自己的堆栈,因此每个线程在调用update()时都会拥有自己的局部变量和方法参数副本。运行时,它会将这些局部变量和方法参数保存到其堆栈中。

但是,方法参数criteria是对可变对象的引用,该对象将存储在Java对象所在的堆上。如果线程可以在同一个ArrayList上调用update(),或者ArrayList中包含的元素可以包含在由不同线程传递到update()的不同调用中的多个ArrayList中,则可能发生同步错误。 / p>

答案 2 :(得分:0)

这一切都取决于您的getClonedCriteria()方法。这是访问共享状态的方法。

您正在创建一个&#34;深层副本&#34;标准,以便每个克隆独立于原始和相互独立。

但是还有一个更微妙的问题,即无论在原型标准上执行什么初始化,都必须任何读取克隆标准的线程之前发生。否则,克隆线程可能会读取未初始化的数据结构版本。

实现此目的的一种方法是在静态初始化程序中初始化原型条件并将其分配给类成员变量。另一种方法是初始化标准,然后将其分配给volatile变量。或者,您可以初始化并将原型(按任意顺序)分配给synchronized块内的普通类或实例成员变量(或使用Lock),然后从另一个块同步读取变量在同一把锁上。