執行緒安全性--synchronized
阿新 • • 發佈:2018-12-01
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修飾類和靜態方法時,鎖定的物件是這個類的所有例項。