1. 程式人生 > >執行緒安全性--synchronized

執行緒安全性--synchronized

synchronized作用範圍

  • 修飾程式碼塊:修飾範圍是大括號括起來的程式碼,作用於呼叫的物件
  • 修飾方法:修飾範圍是整個方法,作用於呼叫物件
  • 修飾靜態方法:修飾範圍是整個靜態方法,作用於所有物件
  • 修飾類:修飾範圍是括號括起來的部分,作用於所有物件
public class SynchronizedBlock {

    public void test(String threadName){
        synchronized (this){
            for (int i=0;i<10;i++){
                System.out.println("test--:"+threadName+"  "+i);
            }
        }
    }

    public synchronized void test2(){
        for (int i=0;i<10;i++){
            System.out.println("test2-i:"+i);
        }
    }

    public static void main(String[] args) {
        final SynchronizedBlock syn1 = new SynchronizedBlock();
        final ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                syn1.test(Thread.currentThread().getName());
            }
        });

        executorService.execute(new Runnable() {
            @Override
            public void run() {
                syn1.test(Thread.currentThread().getName());
            }
        });
    }
}

上述程式碼的執行結果如預期,兩個執行緒按順序輸出0-9

  public static void main(String[] args) {
        final SynchronizedBlock syn1 = new SynchronizedBlock();
        final SynchronizedBlock syn2 = new SynchronizedBlock();
        final ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                syn1.test(Thread.currentThread().getName());
            }
        });

        executorService.execute(new Runnable() {
            @Override
            public void run() {
                syn2.test(Thread.currentThread().getName());
            }
        });
    }

如果是兩個例項,執行結果又會是怎樣呢?

多次的執行結果都不相同。可以看出,synchronized修飾程式碼塊和非靜態方法時,鎖定的物件都只是當前呼叫物件。

public class SynchronizedBlock {

    public void test(String threadName){
        synchronized (SynchronizedBlock.class){
            for (int i=0;i<10;i++){
                System.out.println("test--:"+threadName+"  "+i);
            }
        }
    }

    public synchronized static void test2(String threadName){
        for (int i=0;i<10;i++){
            System.out.println("test2--:"+threadName+"  "+i);
        }
    }

    public static void main(String[] args) {
        final SynchronizedBlock syn1 = new SynchronizedBlock();
        final SynchronizedBlock syn2 = new SynchronizedBlock();
        final ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                syn1.test2(Thread.currentThread().getName());
            }
        });
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                syn2.test2(Thread.currentThread().getName());
            }
        });
    }
}

當synchronized修飾類和靜態方法時,鎖定的物件是這個類的所有例項。