某些特定場景的多執行緒安全問題分析

2021-10-01 10:59:35 字數 1976 閱讀 8066

場景1:

乙個方法中先查詢表中最新的一條資料,然後根據這條資料的值新增另一條資料:

public test1po testtransactional3()
select id, status, value

from test1

order by id desc

limit 1;

由於該方法本身就不是乙個原子操作,即存在多執行緒安全問題,所以給這個方法先加鎖:

public test1po testtransactional3() 

}

另乙個方法中直接新增一條資料:

public test1po testtransactional2()
insert into test1(status, value)

values (#, #);

多執行緒測試:

public void testtransactional1() 

} catch (interruptedexception | brokenbarrierexception e)

}, "t1").start();

new thread(() ->

} catch (interruptedexception | brokenbarrierexception e)

}, "t2").start();

new thread(() ->

} catch (interruptedexception | brokenbarrierexception e)

}, "t3").start();

}

t1和t2測試的是testtransactional3()方法本身的執行緒安全情況,由於通過synchronized加鎖,所以t1和t2之前沒有執行緒安全問題。

t1、t2和t3測試的是testtransactional3()方法和testtransactional2()方法同時執行的時候的執行緒安全情況,結果如下圖所示:

預期的正確情況應該是a0b這條資料應該在a1這條資料的前面。

解決方案1:

讓testtransactional3()方法和testtransactional2()方法對同乙個物件進行加鎖:

public test1po testtransactional2() 

}public test1po testtransactional3()

}

結果如下圖所示:

解決方案2:

讓testtransactional3()方法執行帶where的insert:

public test1po testtransactional2() 

@override

@transactional(rollbackfor = exception.class)

public test1po testtransactional3()

}

insert into test1(status, value)

select #, #

from dual

where exists (select 1 from dual where (select id from test1 order by id desc limit 1) = #);

結果如下圖所示:

問題在於insert可能不成功,這時候需要做另外的操作。

多執行緒安全問題

這裡的安全問題可以理解為 實現在邏輯上的問題,比如 火車站賣票 100張票讓4個人去賣,一定不能出現賣的票是負數問題,那麼開啟多執行緒後,如何才能保證賣的票不可能存在負數呢?常用的解決方法有兩種 1,使用同步 塊,把需要同步的 再放同步 塊中 2,使用同步函式 同步的鎖,可以理解為就是那個物件!同步...

多執行緒(多執行緒的安全問題)

多執行緒的執行出現安全問題。非常可怕的問題,一出問題比較惱火 問題原因 重點 當多條語句在操作同乙個執行緒共享資料時,乙個執行緒對多條語句只執行了一部分,還沒執行完,另乙個執行緒參與進來執行。導致共享資料的錯誤。解決方法 對多條操作共享資料的語句,只能讓乙個執行緒都執行完,在執行過程中,其他執行緒不...

多執行緒的安全問題

首先先提出幾個問題 1.多執行緒程式設計何時會出現執行緒不安全的問題?2.如何解決執行緒不安全的問題?執行緒不安全的本質是多執行緒共享資料,那麼什麼情況下多執行緒會共享資料?無外乎這麼幾種情況 1 多執行緒訪問單例項中的例項變數 2 多執行緒訪問靜態變數 下面將舉例說明,這個例子模擬鐵路售票系統,實...