2017-10-07 103 views
0

你能幫我嗎?在函數中創建一個變量 - 多線程環境

我在Java中有一個函數'f'。該功能在多線程環境中工作

f() { 

SomeObject someO = new SomeObject(); 


    function1(someO); 
    . 
    . 
    . 
    function7(someO); 

} 

的問題:第一個線程進入函數「f」和創建SomeObject的新實例,然後調用功能1,函數2等。當第一個線程在function4中時,稍後的第二個線程進入該方法並創建SomeObject的新的初始化。問題是SomeObject的哪個實例將由函數5,6,7的其餘部分中的第一個線程處理?

+0

來自兩個不同線程的調用將創建兩個不同的實例,將它們分配給兩個不同的局部變量,並將每個實例傳遞給每個函數。你認爲會發生什麼,不同於此,爲什麼? – pvg

回答

1

第一個線程將SomeObject(aka some0)的實例作爲局部變量,因此它是本地的,並因此位於該線程。它只能引用some0的那個實例。

任何其他調用f()的線程都將創建一個不同的實例,也稱爲some0,並且只能引用它的副本。

這些是局部變量的規則。如果some0是一個實例變量 - 即在f()之外聲明 - 那麼如果它們在f()的任何類的同一個實例上調用f(),則該變量可以由不同線程引用。

這些是規則 - 這是一個更完整的解釋。

局部變量在堆棧中聲明;這意味着,對於在方法中聲明的任何變量,在用於該方法的調用的「棧幀」中存在用於其引用的空間。每次調用某個方法時,都會爲該方法中的所有局部變量分配堆棧空間,因此它們的引用與該方法的任何其他調用都是分開的。所以如果一個不同的線程調用這個方法,它會爲本地變量獲取一個不同的棧幀。

同樣的事情發生在遞歸過程中,即如果f()要自己調用。對於f()的每次調用,局部變量引用仍然是分開的,即,每次遞歸調用都有它們自己的副本。否則,使用遞歸將非常困難。

+0

注意到此行爲由Java語言規範保證也很重要。通常這是一個好處:因爲局部變量是每次調用一個方法時重新創建的,所以它們是*線程安全的*,因爲它們與其他調用不共享內存。這通常用於併發編程,以保證局部變量在其他線程可以看到它們之前是安全的。 – markspace

0

第一個線程將處理SomeObject的第一個實例。每個線程創建自己的堆棧。以及它調用的任何方法以及它創建的任何本地對象都將位於該堆棧中,並且這些對象不受其他線程的影響。所以在你的情況下,線程1處理不會受線程2處理影響。