自制樂觀鎖
例 2.2.1.2
package com;
public class Ticket_Opti_MarkToWin {
private int number=4;
private int numberVersion=0;
private synchronized int updAtom(int num,int verNum)
{
int flag;
if(numberVersion==verNum&&number>num){
(購買完整教程)
return flag;
}
void buyOne()
{
/*前面的三句,都只是get,想改只有updAtom里面,
你的buyOne只有改對和不改的權利,沒有改錯的權利*/
int myVersion=numberVersion;
(購買完整教程)
if(flag==1){
System.out.println("買一張成功");
}else{
System.out.println("已經(jīng)進隊等了一會,買一張失敗");
}
}
void buyBatch(int num)
{
int myVersion=numberVersion;
int myNumber=number;
(購買完整教程)
}
}
馬克- to-win:馬克 java社區(qū):防盜版實名手機尾號: 73203。
package com;
class MulThreMarkToWin extends Thread {
Ticket_Opti_MarkToWin ticOpti_MarkToWin;
(購買完整教程)
}
class MulThreMarkToWinBatch extends Thread {
Ticket_Opti_MarkToWin ticOpti_MarkToWin;
(購買完整教程)
}
public class TestConcurBuy_MarkToWin {
public static void main(String[] args) {
Ticket_Opti_MarkToWin ticOpti_MarkToWin=new Ticket_Opti_MarkToWin();
Thread t1 = new MulThreMarkToWin(ticOpti_MarkToWin);
Thread t2 = new MulThreMarkToWinBatch(ticOpti_MarkToWin);
Thread t3 = new MulThreMarkToWin(ticOpti_MarkToWin);
Thread t4 = new MulThreMarkToWin(ticOpti_MarkToWin);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
輸出結果是:
本來還剩4
最后還剩3
買一張成功
本來還剩3
最后還剩2
買一張成功
還沒排隊,就發(fā)現(xiàn)不夠了,所以省時間了,撤了,買幾張失敗
本來還剩2
最后還剩1
買一張成功
輸出結果也有可能是:
本來還剩4
最后還剩1
買幾張成功
本來還剩1
最后還剩0
買一張成功
還沒排隊,就發(fā)現(xiàn)不夠了,所以省時間了,撤了,買一張失敗
還沒排隊,就發(fā)現(xiàn)不夠了,所以省時間了,撤了,買一張失敗
輸出結果也有可能是:
本來還剩4
最后還剩3
買一張成功
已經(jīng)進隊等了一會,買幾張失敗
已經(jīng)進隊等了一會,買一張失敗
本來還剩3
最后還剩2
買一張成功
結論:
馬克-to-win:不論是數(shù)據(jù)庫的select * from table for update; 還是我上面自制的緩存悲觀鎖,樂觀鎖的實現(xiàn),都有個共同的問題:就是它們都是同步請求,都有可能一百萬個線程卡在一個點上,死死等待,直到超時,想退也退不出來。select * from table for update;是卡在數(shù)據(jù)庫的排他鎖上,而我上面自制的緩存悲觀鎖樂觀鎖的實現(xiàn),是卡在synchronized關鍵字上。馬克-to-win:那這個問題怎么解決呢?就用我們java部分的線程那兒學的ReentrantLock的lockInterruptibly()方法,這個方法可以解決我們的 Ticket_Pess_MarkToWin悲觀鎖的問題。而樂觀鎖和select for update的問題還得自己手動加隊列解決。在線程那章也有論述。綜合起來,我還是傾向于ReentrantLock的悲觀鎖,因為自己寫的代碼少。馬克-to-win:不管悲觀樂觀,最終都得一個一個序列完成寫,寫的時間一樣。有關粗略的讀,就普通的看就夠了。要準確的看,就加悲觀鎖就完了。