2015-04-28 178 views
9

在Java中,如果您有以下方法:局部变量和线程安全

public int foo(int n) { 
    int i=n; 
    i = i+1; i = i-1; 
    return i; 
} 

所以在顺序程序的返回值将始终是相同的输入。

即:j == foo(j)

不过,如果你有多个线程调用foo,你能保证j==foo(j)

我会说是的,它是有保证的,因为i是一个局部变量,并且每个线程都有自己的堆栈,所以i将是每个线程不同的内存位置。

我会说你不能保证j==foo(j)如果i是一个实例变量:

private int i; 
public int foo(int n) { 
    i=n; 
    i = i+1; i = i-1; 
    return i; 
} 

因为线程可以交错和i值可以通过一个线程执行的方法来改变半路上,或一个线程可以递增i,但是在它有机会递减之前,另一个线程返回,其输入增加两次并仅递减一次。

+0

你的假设是正确的,但是我会添加一些更可怕的东西:在修改实例变量的情况下,绝对不能保证每个线程的递增和递减顺序都是这样。一个线程可能会看到一个递增,然后是一个递减,另一个看到它们按照相反的顺序发生。 – biziclop

+0

@biziclop我能理解多incremenents或递减,但看到只有一个递减和一个递增的顺序我不明白发生? –

+0

的规则是'在没有的两个操作之间订货前发生时,JVM可以自由地重新排序因为它pleases.'由于是在观察线程运行在修改线程运行的代码和代码之间没有这种关系,观察线程可能以任何顺序查看修改结果。 – biziclop

回答

6

我会说是的,它是有保证的,因为我是一个局部变量,每个线程都有自己的堆栈,所以我将成为每个线程不同的内存位置。

没错。每个对foo的调用都将是独立的,因为foo未使用任何共享状态。

我会说你不能保证当j == FOO(J),如果我是一个可变的实例

正确的一次。听起来你基本上有正确的想法。 (请注意,甚至“增量”和“减量”是不是原子操作,所以如果你有多个线程执行这些操作,你在棘手的情况下结束了。这就是为什么AtomicInteger存在。)

+0

...即使它们是原子,能见度仍然是一个问题。这是AtomicInteger存在的另一个原因。 – biziclop

+0

@biziclop:绝对是。各种各样的东西:) –

+0

谢谢,这样的一个问题,其表示,“在下面的[我的问题第一个代码] Java代码,'Ĵ==富(J)'适用于连续的程序。但是,如果多个线程调用' foo()'然后'j == foo(j)'可能是错误的。解释。“没有意义? –