關於java中的synchronized的用法

今天要分享的內容是synchronized

這個地方也是,說起來知道同步的用法,但是並不是多麼的清楚,和上面的那篇mysql的子查詢一樣,看到代碼中很多這樣寫的。
就順便研究總結一下:

修飾對象有幾種(能出現在什麼地方)

  • 修飾一個類,其作用的範圍是synchronized後面括號括起來的部分, 作用的對象是這個類的所有對象。
  • 修飾一個方法,被修飾的方法稱爲同步方法,其作用的範圍是整個方法, 作用的對象是調用這個方法的對象;
  • 修改一個靜態的方法,其作用的範圍是整個靜態方法, 作用的對象是這個類的所有對象;
  • 修飾一個代碼塊,被修飾的代碼塊稱爲同步語句塊,其作用的範圍是大括號{}括起來的代碼, 作用的對象是調用這個代碼塊的對象;

2個鎖

上面的4種情況,核心也就是,2個鎖

  1. 對象鎖,修飾一個類的成員方法和代碼塊,就是這種情況,他強調的是創建對象,調用對象本身,比如,a對象和b對象完全不同
  2. 類鎖(其實沒有,類比概念,好理解),也就是修飾類,和靜態的方法,這兩種的同步是一樣的,他們強調的是類class這個對象的鎖,因此a對象和b對象擁有同樣的鎖,所以是相同的

廢話不多說,直接上例子吧

/**
 * @author hankun
 * @create 2017-07-05 19:52
 */
public class synchronizedTest {


    /**
     * 同步線程,修飾方法塊
     */
    static class SyncMehtodBlock implements Runnable {
        private static int count;

        public SyncMehtodBlock() {
            count = 0;
        }

        public void run() {
            synchronized (this) {
                System.out.println(Thread.currentThread().getName() + "開始..SyncMehtodBlock");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "結束..SyncMehtodBlock");
            }
        }

    }


    /**
     * 同步線程,修飾方法
     */
    static class SyncMehtod extends Thread {
        private synchronizedTest syn;

        public SyncMehtod(synchronizedTest synchronizedTest) {
            this.syn = synchronizedTest;
        }

        public void run() {
            syn.test();
        }

    }

    public synchronized void test() {
        System.out.println(Thread.currentThread().getName() + "開始..SyncMehtod");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "結束..SyncMehtod");
    }


    /**
     * 同步線程,修飾靜態方法
     */
    static class SyncStaticMehtod extends Thread {

        public synchronized static void staticTest() {
            System.out.println(Thread.currentThread().getName() + "開始..SyncStaticMehtod");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "結束..SyncStaticMehtod");
        }

        public void run() {
            staticTest();
        }

    }

    /**
     * 同步線程,修飾類
     */
    static class SyncClass extends Thread {

        public void classTest() {
            synchronized (synchronizedTest.class) {
                System.out.println(Thread.currentThread().getName() + "開始..SyncClass");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "結束..SyncClass");
            }
        }

        public void run() {
            classTest();
        }

    }


    public static void main(String[] args) {
        //情況1,修飾方法塊
        SyncMehtodBlock syncMehtodBlock = new SyncMehtodBlock();
        Thread thread1 = new Thread(syncMehtodBlock, "syncMehtodBlock1");
        Thread thread2 = new Thread(syncMehtodBlock, "syncMehtodBlock2");
        thread1.start();
        thread2.start();


        //情況2,修飾方法
        synchronizedTest syn = new synchronizedTest();
        SyncMehtod syncMehtod3 = new SyncMehtod(syn);
        SyncMehtod syncMehtod4 = new SyncMehtod(syn);
        syncMehtod3.start();
        syncMehtod4.start();


        //情況3,修飾靜態方法
        SyncStaticMehtod a = new SyncStaticMehtod();
        SyncStaticMehtod b = new SyncStaticMehtod();
        Thread thread5 = new Thread(a, "SyncStaticMehtod1");
        Thread thread6 = new Thread(b, "SyncStaticMehtod2");
        thread5.start();
        thread6.start();


        //情況4,修飾類
        SyncClass c = new SyncClass();
        SyncClass d = new SyncClass();
        Thread thread7 = new Thread(c, "SyncClass1");
        Thread thread8 = new Thread(d, "SyncClass2");
        thread7.start();
        thread8.start();

    }
}

我寫了一個,模擬4種情況的例子,報每個類型都包含進去了

請注意觀察裏面的synchronized的關鍵位置,出現的情況,以及每個測試例子,是如何新建的,區分不同

所有的例子,都是具有同步的,因爲競爭,比如,a先開始,那麼a先結束,然後才能輪到b開始,b結束

好好,體會裏面的內容

總結

  1. 無論synchronized關鍵字加在方法上還是對象上,如果它作用的對象是非靜態的,則它取得的鎖是對象;如果synchronized作用的對象是一個靜態方法或一個類,則它取得的鎖是對類,該類所有的對象同一把鎖。
  2. 每個對象只有一個鎖(lock)與之相關聯,誰拿到這個鎖誰就可以運行它所控制的那段代碼。
  3. 實現同步是要很大的系統開銷作爲代價的,甚至可能造成死鎖,所以儘量避免無謂的同步控制。

我覺得別人說的,這三句話,已經說的很明白不過,我也就不加自己的體會了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章