当两个线程同时调用相同的静态方法时会发生什么?

时间:2014-02-18 20:39:27

标签: java multithreading static synchronized

当两个线程同时调用相同的静态方法时会发生什么?例如:

public static String someMethod(){

    //some logic, can take about 1 second to process

    return new String(result);
}

第一个线程现在调用someMethod()。 第二个线程从现在起0.5秒后调用someMethod()(第一个线程仍在处理数据)。

我知道someMethod()可以同步。但如果它不同步会发生什么?

4 个答案:

答案 0 :(得分:20)

调用方法时,JVM会为执行线程中的调用创建堆栈帧。此框架包含方法中声明的所有局部变量。在任何不访问字段的方法(静态或其他方法)的情况下,每个执行在每个线程上完全独立地进行。如果该方法在其计算中使用参数,则这些参数也位于堆栈帧中,并且多个调用不会相互干扰。

答案 1 :(得分:11)

这取决于你的方法是否改变了外部状态。

static long i = 0l;
public static String someMethod(){
    String accm = "";
    for(;i < Integer.MAX_VALUE*20/*Just to make sure word tearing occurs*/; i++)
        accm += i
    return accm;
}

会导致问题:

  • 不保证多头可以原子设置,因此可能会被“撕裂”(Spec
  • ++不是原子操作。它与{int n = i; i = i + 1; return n}完全相同
    • i = i + 1也不是原子的,如果它在中间变化,一些值将重复
    • n的返回可能是陈旧的

但如果i是一个局部变量,那么就没有问题。只要任何外部状态在被读取时保证不变,就永远不会有任何问题。

答案 2 :(得分:4)

该方法是静态的这一事实无关紧要。他们的问题应该是有问题的代码操纵状态变量

  • 如果没有读/写任何实例/类的成员,那么应该没有问题。
  • 在写入操作的情况下,需要某种同步
  • 如果只有读取,则不一定意味着该方法很好地同步。这取决于数据的写入方式和线程。例如,如果代码读取在写操作期间受监视器M保护的V,那么V的读取也必须在同一监视器上同步。

答案 3 :(得分:0)

如果两个语句在不同的线程中执行,则无法保证第一个线程更改对第二个线程可见,除非您通过同步{在这两个语句之间建立发生之前的关系{1}}使用给定的同步策略。换句话说,如果您正在写入相同的变量,然后同时从两个线程读取,那么您的逻辑可能会产生意外和不可预测的结果。