自制樂(lè)觀鎖

例 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){
(購(gòu)買完整教程)
        return flag;
    }
  
    void buyOne()
    {
/*前面的三句,都只是get,想改只有updAtom里面,
 你的buyOne只有改對(duì)和不改的權(quán)利,沒(méi)有改錯(cuò)的權(quán)利*/      
        int myVersion=numberVersion;
(購(gòu)買完整教程)
        if(flag==1){
            System.out.println("買一張成功");
        }else{
            System.out.println("已經(jīng)進(jìn)隊(duì)等了一會(huì),買一張失敗");
        }
    }
  
    void buyBatch(int num)
    {
        int myVersion=numberVersion;
        int myNumber=number;
(購(gòu)買完整教程)
    }
  
}




馬克- to-win:馬克 java社區(qū):防盜版實(shí)名手機(jī)尾號(hào): 73203。

package com;
class MulThreMarkToWin extends Thread {
    Ticket_Opti_MarkToWin ticOpti_MarkToWin;
(購(gòu)買完整教程)
}
class MulThreMarkToWinBatch extends Thread {
    Ticket_Opti_MarkToWin ticOpti_MarkToWin;
(購(gòu)買完整教程)
}
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();
    }
}




輸出結(jié)果是:

本來(lái)還剩4
最后還剩3
買一張成功
本來(lái)還剩3
最后還剩2
買一張成功
還沒(méi)排隊(duì),就發(fā)現(xiàn)不夠了,所以省時(shí)間了,撤了,買幾張失敗
本來(lái)還剩2
最后還剩1
買一張成功


輸出結(jié)果也有可能是:


本來(lái)還剩4
最后還剩1
買幾張成功
本來(lái)還剩1
最后還剩0
買一張成功
還沒(méi)排隊(duì),就發(fā)現(xiàn)不夠了,所以省時(shí)間了,撤了,買一張失敗
還沒(méi)排隊(duì),就發(fā)現(xiàn)不夠了,所以省時(shí)間了,撤了,買一張失敗


輸出結(jié)果也有可能是:


本來(lái)還剩4
最后還剩3
買一張成功
已經(jīng)進(jìn)隊(duì)等了一會(huì),買幾張失敗
已經(jīng)進(jìn)隊(duì)等了一會(huì),買一張失敗
本來(lái)還剩3
最后還剩2
買一張成功



結(jié)論:

馬克-to-win:不論是數(shù)據(jù)庫(kù)的select * from table for update; 還是我上面自制的緩存悲觀鎖,樂(lè)觀鎖的實(shí)現(xiàn),都有個(gè)共同的問(wèn)題:就是它們都是同步請(qǐng)求,都有可能一百萬(wàn)個(gè)線程卡在一個(gè)點(diǎn)上,死死等待,直到超時(shí),想退也退不出來(lái)。select * from table for update;是卡在數(shù)據(jù)庫(kù)的排他鎖上,而我上面自制的緩存悲觀鎖樂(lè)觀鎖的實(shí)現(xiàn),是卡在synchronized關(guān)鍵字上。馬克-to-win:那這個(gè)問(wèn)題怎么解決呢?就用我們java部分的線程那兒學(xué)的ReentrantLock的lockInterruptibly()方法,這個(gè)方法可以解決我們的 Ticket_Pess_MarkToWin悲觀鎖的問(wèn)題。而樂(lè)觀鎖和select for update的問(wèn)題還得自己手動(dòng)加隊(duì)列解決。在線程那章也有論述。綜合起來(lái),我還是傾向于ReentrantLock的悲觀鎖,因?yàn)樽约簩懙拇a少。馬克-to-win:不管悲觀樂(lè)觀,最終都得一個(gè)一個(gè)序列完成寫,寫的時(shí)間一樣。有關(guān)粗略的讀,就普通的看就夠了。要準(zhǔn)確的看,就加悲觀鎖就完了。