Java多線程-線程的鎖總結


一、多線程-同步函數的鎖是this



/*
同步函數用的是哪一個鎖呢?
函數需要被對象調用。那么函數都有一個所屬對象引用。就是this。
所以同步函數使用的鎖是this。

通過該程序進行驗證。

使用兩個線程來買票。
一個線程在同步代碼塊中。    這兩個的鎖不一樣
一個線程在同步函數中。
都在執行買票動作。


*/


class Ticket implements Runnable
{
    private  int tick = 100;
    Object obj = new Object();
    boolean flag = true;
    public  void run()
    {
        if(flag)
        {
            while(true)
            {
                synchronized(this)    /*同步函數的鎖*/
                {
                    if(tick>0)
                    {
                        try{Thread.sleep(10);}catch(Exception e){}
                        System.out.println(Thread.currentThread().getName()+"....code : "+ tick--);
                    }
                }
            }
        }
        else
            while(true)
                show();           /*使用this鎖*/
    }
    public synchronized void show()//this
    {
        if(tick>0)
        {
            try{Thread.sleep(10);}catch(Exception e){}
            System.out.println(Thread.currentThread().getName()+"....show.... : "+ tick--);
        }
    }
}


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

        Ticket t = new Ticket();

        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);
        t1.start();
        try{Thread.sleep(10);}catch(Exception e){}
        t.flag = false;
        t2.start();


//        Thread t3 = new Thread(t);
//        Thread t4 = new Thread(t);
//        t3.start();
//        t4.start();


    }
}

 

二、多線程-靜態同步函數的鎖是class對象


/*
如果同步函數被靜態修飾后,使用的鎖是什么呢?

通過驗證,發現不在是this。因為靜態方法中也不可以定義this。

靜態進內存是,內存中沒有本類對象,但是一定有該類對應的字節碼文件對象。
類名.class  該對象的類型是Class


靜態的同步方法,使用的鎖是該方法所在類的字節碼文件對象。 類名.class
*/
class Ticket implements Runnable
{
    private static  int tick = 100;
    //Object obj = new Object();
    boolean flag = true;
    public  void run()
    {
        if(flag)
        {
            while(true)
            {
                synchronized(Ticket.class)           /*使用了靜態,鎖就變了*/
                {
                    if(tick>0)
                    {
                        try{Thread.sleep(10);}catch(Exception e){}
                        System.out.println(Thread.currentThread().getName()+"....code : "+ tick--);
                    }
                }
            }
        }
        else
            while(true)
                show();
    }
    public static synchronized void show()
    {
        if(tick>0)
        {
            try{Thread.sleep(10);}catch(Exception e){}
            System.out.println(Thread.currentThread().getName()+"....show.... : "+ tick--);
        }
    }
}


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

        Ticket t = new Ticket();

        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);
        t1.start();
        try{Thread.sleep(10);}catch(Exception e){}
        t.flag = false;
        t2.start();


    }
}

三、多線程-單例設計模式-懶漢式 出現的安全問題


/*
單例設計模式。 必須要記住,面試題
餓漢式與懶漢式的區別
1.懶漢式是延時加載的形式
2.懶漢式由於是延時加載,所以在多線程中會出現安全問題
3.可以加同步函數或者同步代碼塊來解決,而同步函數每次都需要判斷比較慢
4.這里采用同步代碼塊來解決安全問題
5.由於函數是靜態的,所以鎖是類名.class

*/
//餓漢式。
/*
class Single
{
    private static final Single s = new Single();
    private Single(){}
    public static Single getInstance()
    {
        return s;
    }
}
*/


//懶漢式           

class Single
{
    private static Single s = null;
    private Single(){}


    public static  Single getInstance()
    {
        if(s==null)
        {
            synchronized(Single.class)
            {
                if(s==null)
                    //--->A;
                    s = new Single();
            }
        }
        return s;
    }
}

class SingleDemo
{
    public static void main(String[] args)
    {
        System.out.println("Hello World!");
    }
}

 

 

四、死鎖(要避免出現和熟悉)



class Test implements Runnable
{
    private boolean flag;
    Test(boolean flag)
    {
        this.flag = flag;
    }

    public void run()
    {
        if(flag)
        {
            while(true)
            {
                synchronized(MyLock.locka)
                {
                    System.out.println(Thread.currentThread().getName()+"...if locka ");
                    synchronized(MyLock.lockb)
                    {
                        System.out.println(Thread.currentThread().getName()+"..if lockb");                    
                    }
                }
            }
        }
        else
        {
            while(true)
            {
                synchronized(MyLock.lockb)
                {
                    System.out.println(Thread.currentThread().getName()+"..else lockb");
                    synchronized(MyLock.locka)
                    {
                        System.out.println(Thread.currentThread().getName()+".....else locka");
                    }
                }
            }
        }
    }
}


class MyLock
{
    static Object locka = new Object();     /*靜態,能用類名直接調用*/
    static Object lockb = new Object();
}

class  DeadLockTest
{
    public static void main(String[] args)
    {
        Thread t1 = new Thread(new Test(true));
        Thread t2 = new Thread(new Test(false));
        t1.start();
        t2.start();
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM