java之Synchronized(鎖住對(duì)象和鎖住代碼)

1、問(wèn)題

Synchronized我們一般都知道是鎖,但是我們?cè)趺磪^(qū)分是鎖對(duì)象還是鎖代碼呢?

2、測(cè)試Demo

    package leetcode.chenyu.test;
     
    public class Synchronized {
       
         class Test {
            public synchronized  void testFirst() {
                print("testFirst");
            }
           
            public void testSecond() {
                synchronized(this) {
                    print("testSecond");
                }
            }
           
            public void testThird() {
                synchronized(Test.class) {
                    print("testThird");
                }
            }
           
            public  void print(String method) {
                System.out.println(method + "start");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(method + "end");
            }
        }
           
        class TestThread extends Thread {
           
            public int mType = 0;
            public Test mTest = null;
           
            public TestThread(int type, Test test) {
                this.mType = type;
                this.mTest = test;
            }
           
            public void run() {
                if (mTest == null) {
                    if (mType == 1) {
                        Test test = new Test();
                        test.testFirst();
                    }
                    else if (mType == 2) {
                        Test test = new Test();
                        test.testSecond();
                    }
                    else if (mType == 3) {
                        Test test = new Test();
                        test.testThird();
                    }
                } else {
                    if (mType == 1) {
                        mTest.testFirst();
                    }
                    else if (mType == 2) {
                        mTest.testSecond();
                    }
                    else if (mType == 3) {
                        mTest.testThird();
                    }
                }
            }
        }
       
        public static void main(String[] args) {
            Synchronized syn = new Synchronized();
            Test test = syn.new Test();
                for (int i = 0; i < 5; ++i) {
                    syn.new TestThread(1, null).start();
            }
        }
    }

 
3、運(yùn)行結(jié)果和分析


1)、按照上面的運(yùn)行結(jié)果

    testFirststart
    testFirststart
    testFirststart
    testFirststart
    testFirststart
    testFirstend
    testFirstend
    testFirstend
    testFirstend
    testFirstend


2)、把for循環(huán)里面的代碼換如下

syn.new TestThread(2, null).start();

運(yùn)行結(jié)果如下

    testSecondstart
    testSecondstart
    testSecondstart
    testSecondstart
    testSecondstart
    testSecondend
    testSecondend
    testSecondend
    testSecondend
    testSecondend

對(duì)于上面1)、2)、兩種情況,synchronized(this)以及非static的synchronized方法,只能防止多個(gè)線(xiàn)程同時(shí)執(zhí)行同一個(gè)對(duì)象的同步代碼段,鎖的是對(duì)象,也就是鎖的本身this, 由于每個(gè)線(xiàn)程都新構(gòu)建了一個(gè)新的對(duì)象,所以加了synchronized沒(méi)有鎖住。

3)、把for循環(huán)里面的代碼換如下

syn.new TestThread(1, test).start();

syn.new TestThread(2, test).start();

運(yùn)行結(jié)果都一樣如下

    testSecondstart
    testSecondend
    testSecondstart
    testSecondend
    testSecondstart
    testSecondend
    testSecondstart
    testSecondend
    testSecondstart
    testSecondend

這里由于我們幾個(gè)現(xiàn)場(chǎng)都共用一個(gè)對(duì)象,所以對(duì)象固定了,所以就鎖住了,其它線(xiàn)程在沒(méi)有釋放鎖的時(shí)候,進(jìn)不來(lái)。

4)、把for循環(huán)里面的代碼換如下

syn.new TestThread(3, null).start();

syn.new TestThread(3, test).start();

結(jié)果都如下

    testThirdstart
    testThirdend
    testThirdstart
    testThirdend
    testThirdstart
    testThirdend
    testThirdstart
    testThirdend
    testThirdstart
    testThirdend

synchronized(Test.class)實(shí)現(xiàn)了全局鎖的效果,不管對(duì)象是不是一樣的,都是同樣的效果,就鎖住代碼了


我么一般用這個(gè)比較多。

 
4、總結(jié)

1、synchronized加在非靜態(tài)方法前和synchronized(this)都是鎖住了這個(gè)類(lèi)的對(duì)象,如果多線(xiàn)程訪(fǎng)問(wèn),對(duì)象不同,就鎖不住,對(duì)象固定是一個(gè),就可鎖住。

2、synchronized(類(lèi)名.class)和加在靜態(tài)方法前,是鎖住了代碼塊,不管多線(xiàn)程訪(fǎng)問(wèn)的時(shí)候?qū)ο笫遣皇峭粋€(gè),能縮小代碼段的范圍就盡量縮小,能在代碼段上加同步就不要再整個(gè)方法上加同步,縮小鎖的粒度。


4、總結(jié)





作者:chen.yu
深信服三年半工作經(jīng)驗(yàn),目前就職游戲廠(chǎng)商,希望能和大家交流和學(xué)習(xí),
微信公眾號(hào):編程入門(mén)到禿頭 或掃描下面二維碼
零基礎(chǔ)入門(mén)進(jìn)階人工智能(鏈接)