關(guān)于多線程的一些知識點(二)——臨界資源

臨界資源問題

先看例子

public class SourceConflict {

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                while (TicketCenter.currnetTicket > 0) {
                    System.out.println(Thread.currentThread().getName()+"賣出一張票,剩余"+ --TicketCenter.currnetTicket);
                }
            }
        };
        
        Thread t1 = new Thread(runnable, "t1");
        Thread t2 = new Thread(runnable, "t2");
        Thread t3 = new Thread(runnable, "t3");
        Thread t4 = new Thread(runnable, "t4");
        
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
    
    
}

class TicketCenter{
    public static int currnetTicket = 100;
}

運行程序,四個線程共享ticket資源,會同時操作票資源,不做處理會出現(xiàn)下面的問題


image.png

解決方法一:同步代碼段

public class SynchronizedDemo {
    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                while (TicketCenter.currnetTicket > 0) {
                    //對象鎖
                    synchronized ("") {
                        System.out.println(Thread.currentThread().getName()+"賣出一張票,剩余"+ --TicketCenter.currnetTicket);
                    }
                }
            }
        };
        
        Thread t1 = new Thread(runnable, "t1");
        Thread t2 = new Thread(runnable, "t2");
        Thread t3 = new Thread(runnable, "t3");
        Thread t4 = new Thread(runnable, "t4");
        
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

上面的 //對象鎖 synchronized ("") 可替換成
//類鎖 synchronized(SynchronizedDemo.class)
只要保證四個線程看到的是同一所即可,
synchronized(new SynchronizedDemo())會報錯,因為每次都會生成不同對象

好接下來我們看運行代碼結(jié)果(我們的結(jié)果不一定相同)


image.png

但是?。。。。。。。?/p>

image.png

這是因為t2賣票時,t1,t3,t4拿到資源在鎖外等待,線程切換的時候,他們看到的票數(shù)還是>0的,當t2賣出最后一張,票數(shù)為0,t1,t3,t4再做賣票動作時,會產(chǎn)生負數(shù)。

修改成這樣就好了

synchronized ("") {
                        if (TicketCenter.currnetTicket == 0) {
                            return;
                        }
                        System.out.println(Thread.currentThread().getName()+"賣出一張票,剩余"+ --TicketCenter.currnetTicket);
                    }

解決方法二:同步方法

public class SynchronizedFunction {

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                while (TicketCenter.currnetTicket > 0) {
                    sell();
                }
            }
        };
        
        Thread t1 = new Thread(runnable, "t1");
        Thread t2 = new Thread(runnable, "t2");
        Thread t3 = new Thread(runnable, "t3");
        Thread t4 = new Thread(runnable, "t4");
        
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
    
    /*同步方法
    靜態(tài)方法:同步鎖就是類鎖, 當前類.class
    非靜態(tài)方法: 同步鎖是 this*/
    public synchronized static void sell(){
        if (TicketCenter.currnetTicket == 0) {
            return;
        }
        System.out.println(Thread.currentThread().getName()+"賣出一張票,剩余"+ --TicketCenter.currnetTicket);
    }
}

看結(jié)果


image.png

當需要同步的邏輯比較復雜的時候可以將他們放在方法里

解決方法三:顯示鎖

public class LockDemo {
public static void main(String[] args) {

    final ReentrantLock lock = new ReentrantLock();
    
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            // TODO Auto-generated method stub
            while (TicketCenter.currnetTicket > 0) {
                //對臨界資源加上顯示鎖
                lock.lock();
                if (TicketCenter.currnetTicket <= 0) {
                    return;
                }
                
                System.out.println(Thread.currentThread().getName()+"賣出一張票,剩余"+ --TicketCenter.currnetTicket);
                //對臨界資源釋放鎖
                lock.unlock();
            }
        }
    };
    
    Thread t1 = new Thread(runnable, "t1");
    Thread t2 = new Thread(runnable, "t2");
    Thread t3 = new Thread(runnable, "t3");
    Thread t4 = new Thread(runnable, "t4");
    
    t1.start();
    t2.start();
    t3.start();
    t4.start();
}

}
結(jié)果沒有問題,但是。。。
運行之后程序沒有停止,有大佬可以告訴我為什么嗎?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容