2016-08-19 80 views
1

我在多線程enviornment靜態方法行爲

Class TestClass{ 

    public static TestObject updateTestObject (TestObject testObject) 
    { 
     testObject.setLatestSequence (testObject.getLatestSequence() + 1); 

     return testObject ; 
    } 

}

更新的值的值在這樣的另一個類使用。該函數是同步的,因此一次只能有一個線程進入。

Class parentClass 
{ 

void synchronized updateDBSequence() 
{ 
     // Read old value from DB  
     TestObject testObject = readFromDAO.readTestClass(naturalKey); 

    // Access in static manner, Issue ? If two threads go in, the object  
    //the return will have duplicate sequence number in it e.g. first read    
    //1 as latest sequence second also read 1 and both updated it to 2 and save in DB. 

    TestClass.updateTestObject (testObject); 

    // DAO has already been injected by spring 
    // Update value in DB 
    testObjectDAO.update (testObject); 
    } 

當這樣在多線程運行enviornment,有時,從testClass.updateTestObject對象返回()方法有重複的序列且因此重複序列被保存在DB中。我們希望它們始終是唯一的

爲了解決這個問題,函數updateDBSequence()已經被同步化了,但是這並沒有解決問題,然後意識到TestClass.updateTestObject()函數可能會導致這個問題,因爲它是靜態的,進入它的線程不會知道其他線程已經更新了值。

所以爲了解決這個問題,Class.function方式訪問被其中的實際代碼改變了,而不是在代碼中調用帶有類名的靜態函數。

void synchronized updateDBSequence() 
    { 
     // Read old value from DB  
     TestObject testObject = readFromDAO.readTestClass(naturalKey); 

    // DO not access in static manner 
     testObject.setLatestSequence (testObject.getLatestSequence() + 1); 


    // DAO has already been injected by spring 
    // Update value in DB 
    testObjectDAO.update (testObject); 
    } 

它會解決這個問題嗎?使用靜態方法的線程是否不知道其他線程更新的值,即他們正在處理的對象是共享的,並且每個線程都有自己的副本。

+2

使用真正的數據庫序列。 –

+0

但是在這種情況下線程的行爲呢? – Aiden

+1

'無效同步功能updateDBSequence()'?這不是Java。 – Kayaman

回答

1

testObject.setLatestSequence (testObject.getLatestSequence() + 1);

不是原子的。

updateDBSequence()如果您使用parentClass以上的多個實例,它們也不是原子。

您提出的修改(使用實例)不會改變任何事情。 要做的最好的事情是使用交易,而不是重新發明輪子。

快速修復將在TestClass上進行同步。

void updateDBSequence() 
{ 
    synchronized (TestClass.class) { 
     // Read old value from DB  
     TestObject testObject = readFromDAO.readTestClass(naturalKey); 

     TestClass.updateTestObject (testObject); 

     testObjectDAO.update (testObject); 

    } 
} 

這將解決updateDBSequence()併發呼叫之間的問題。如果在其他方法中使用TestClassreadFromDAO,將會出現數據爭用條件。

+0

如果'TestClass.updateTestObject(testObject);'另外在別處同時被調用而沒有同步......只是一個想法,這將無濟於事。 – Fildor

+0

是的。我只和我給的東西一起工作。 – UmNyobe

+0

當然,只是想要提及它。 – Fildor