1. 程式人生 > >java同步機制物件鎖使用方式比較

java同步機制物件鎖使用方式比較

class Sync {

    private byte[] lock = new byte[0];

    public void sync() throws InterruptedException {

        synchronized (lock) {
            runThread();
        }

    }

    public void thisSync() throws InterruptedException {

        synchronized (this) {
            runThread();
        }

    }

    public synchronized static void staticSync() throws InterruptedException { // 同步的static 函式
        runThread();
    }

    public void classSync() throws InterruptedException { //

        synchronized (Sync.class) {
            runThread();
        }
    }

    private static void runThread() throws InterruptedException {

        Thread current = Thread.currentThread();
        System.out.println("current thread id:" + current.getId() + "enter...");

        System.out.println("1111");
        Thread.sleep(1000);
        System.out.println("2222");
        Thread.sleep(1000);
        System.out.println("3333");
        Thread.sleep(1000);
        System.out.println("4444");
        Thread.sleep(1000);
        System.out.println("5555");

        System.out.println("current thread id:" + current.getId() + "out...");

    }

}


1.同一個執行緒lock物件鎖是否可複用(即不用等待)

結論:可複用

public class TestObjectSyncLock {

    private static byte[] lock = new byte[0];//零長度的byte陣列物件建立起來將比任何物件都經濟――檢視編譯後的位元組碼:生成零長度的byte[]物件只需3條操作碼,而Object lock = new Object()則需要7行操作碼。 

    public static void main(String[] args) throws InterruptedException {

    //1.同一個執行緒lock物件鎖是否可複用(即不用等待)----可複用
        
        synchronized (lock) {

            new Thread(new Runnable() {

                public void run() {

                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("aaa");

                }
            }).start();
            // lock.notify();
        }

        synchronized (lock) {

            System.out.println("bbb");
            // lock.wait();
        }
   }
}

結果:

bbb
aaa

2.同一個物件,多執行緒訪問(一個主執行緒,一個新開執行緒)

結論:鎖有效

  Thread current = Thread.currentThread();  
       System.out.println("current thread id:"+current.getId()+"start...");
       final Sync sync =new Sync();
       
        new Thread(new Runnable() {
            
            public void run() {
                Thread current = Thread.currentThread();  
                System.out.println("current thread id:"+current.getId()+"start...");
                try {
                    sync.sync();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }  
                
            }
        }).start();
        
        sync.sync();

結果:

current thread id:1start...
current thread id:1enter...
1111
current thread id:9start...
2222
3333
4444
5555
current thread id:1out...
current thread id:9enter...
1111
2222
3333
4444
5555
current thread id:9out...

3.不同物件,多執行緒訪問

結論:鎖無效

 Thread current = Thread.currentThread();
        System.out.println("currret thread id:" + current.getId() + "start...");
        final Sync sync = new Sync();
        final Sync sync2 = new Sync();

        new Thread(new Runnable() {

            public void run() {
                Thread current = Thread.currentThread();
                System.out.println("currret thread id:" + current.getId() + "start...");
                try {
                    sync2.sync();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }).start();

        sync.sync();

結果:

currret thread id:1start...
current thread id:1enter...
1111
currret thread id:9start...
current thread id:9enter...
1111
2222
2222
3333
3333
4444
4444
5555
current thread id:1out...
5555
current thread id:9out...

4.wait(),notify()----呼叫wait或notify時,該執行緒必須是該物件鎖的所有者,否則會丟擲Exception in thread "Thread-0" java.lang.IllegalMonitorStateException

 new Thread(new Runnable() {

            public void run() {

                System.out.println("------");
                synchronized (lock) {
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    lock.notify();
                    System.out.println(" after notify ...");
                }
            }
        }).start();

        synchronized (lock) {

            System.out.println("enter ...");

            lock.wait();

            System.out.println("out ...");

        }

結果:

enter ...
------
 after notify ...
out ...

5.wait(),notifyAll()----notifyAll()喚醒所有正在wait的不同執行緒

    new Thread(new Runnable() {

            public void run() {
                synchronized (lock) {
                    System.out.println("enter thread 1 ...");

                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println("leave thread 1 ...");
                }
            }
        }).start();

        new Thread(new Runnable() {

            public void run() {
                synchronized (lock) {
                    System.out.println("enter thread 2 ...");

                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println("leave thread 2 ...");
                }
            }
        }).start();

        new Thread(new Runnable() {

            public void run() {

                System.out.println("------");
                synchronized (lock) {
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    lock.notifyAll();// notifyAll方法會喚醒所有正在等待物件控制權的執行緒。
                    // lock.notify();//隨機通知一個正在等待的執行緒
                    System.out.println("after notifyAll ...");
                }
            }
        }).start();

結果:

enter thread 1 ...
enter thread 2 ...
------
after notifyAll ...
leave thread 2 ...
leave thread 1 ...

6.static 同步方法,不同物件

 Thread current = Thread.currentThread();
        System.out.println("currret thread id:" + current.getId() + "start...");
        Sync sync = new Sync();

        new Thread(new Runnable() {

            public void run() {
                Sync sync = new Sync();
                Thread current = Thread.currentThread();
                System.out.println("currret thread id:" + current.getId() + "start...");
                try {
                    sync.staticSync();// 鎖有效
                    // Sync.staticSync();//鎖有效
                    // sync.sync();//鎖無效
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }).start();

        sync.staticSync();// 鎖有效
        // Sync.staticSync();//鎖有效
        // sync.sync();//鎖無效

結果:

currret thread id:1start...
current thread id:1enter...
1111
currret thread id:9start...
2222
3333
4444
5555
current thread id:1out...
current thread id:9enter...
1111
2222
3333
4444
5555
current thread id:9out...

7.class 同步方法,不同物件

 Thread current = Thread.currentThread();
        System.out.println("currret thread id:" + current.getId() + "start...");
        Sync sync = new Sync();

        new Thread(new Runnable() {

            public void run() {
                Sync sync = new Sync();
                Thread current = Thread.currentThread();
                System.out.println("currret thread id:" + current.getId() + "start...");
                try {
                    sync.classSync();// 鎖有效

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }).start();

        sync.classSync();// 鎖有效

結果:

currret thread id:1start...
current thread id:1enter...
1111
currret thread id:9start...
2222
3333
4444
5555
current thread id:1out...
current thread id:9enter...
1111
2222
3333
4444
5555
current thread id:9out...

8.this 同步方法,不同物件,跟2一樣,物件鎖

  final Sync sync = new Sync();
        new Thread(new Runnable() {

            public void run() {
                // Sync sync =new Sync();
                Thread current = Thread.currentThread();
                System.out.println("currret thread id:" + current.getId() + "start...");
                try {
                    sync.thisSync();

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }).start();

        new Thread(new Runnable() {

            public void run() {
                // Sync sync =new Sync();
                Thread current = Thread.currentThread();
                System.out.println("currret thread id:" + current.getId() + "start...");
                try {
                    sync.thisSync();

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }).start();

結果:

currret thread id:9start...
current thread id:9enter...
1111
currret thread id:10start...
2222
3333
4444
5555
current thread id:9out...
current thread id:10enter...
1111
2222
3333
4444
5555
current thread id:10out...