首先來回顧一下synchronized的基本使用:
synchronized代碼塊,被修飾的代碼成為同步語句塊,其作用的范圍是調用這個代碼塊的對象,我們在用synchronized關鍵字的時候,能縮小代碼段的范圍就盡量縮小,能在代碼段上加同步就不要再整個方法上加同步。這叫減小鎖的粒度,使代碼更大程度的并發。 synchronized方法,被修飾的方法成為同步方法,其作用范圍是整個方法,作用對象是調用這個方法的對象。 synchronized靜態方法,修飾一個static靜態方法,其作用范圍是整個靜態方法,作用對象是這個類的所有對象。 synchronized類,其作用范圍是Synchronized后面括號括起來的部分synchronized(className.class),作用的對象是這個類的所有對象。 synchronized() ()中是鎖住的對象, synchronized(this)鎖住的只是對象本身,同一個類的不同對象調用的synchronized方法并不會被鎖住,而synchronized(className.class)實現了全局鎖的功能,所有這個類的對象調用這個方法都受到鎖的影響,此外()中還可以添加一個具體的對象,實現給具體對象加鎖。synchronized (object) { //在同步代碼塊中對對象進行操作 }synchronized關鍵字與線程安全
以為用了synchronized關鍵字包住了代碼就可以線程同步安全了。測試了下。發現是完全的錯了。synchronized必須正確的使用才是真正的線程安全。。。雖然知道這種寫法,一直以為卻由于懶而用了錯誤的方法。
看來基礎還沒有打好。仍需復習加強!工作中犯這種錯誤是不可原諒的,要知道使用synchronized關鍵字的地方都是數據敏感的!汗一把。。。
先貼代碼:
package com; public class ThreadTest { public static void main(String[] args) { MyThread m1 = new MyThread(1); MyThread m2 = new MyThread(2); m1.start(); m2.start(); } } final class MyThread extends Thread { private int val; public MyThread(int v) { val = v; } //這種做法其實是非線程安全的 public synchronized void print1(int v) { for (int i = 0; i < 100; i++) { System.out.print(v); } } public void print2(int v) { //線程安全 synchronized (MyThread.class) { for (int i = 0; i < 100; i++) { System.out.print(v); } } } public void run() { print1(val); // print2(val); } } 還是為了偷懶,汗一把。。。程序員總是懶的吧。能少寫就少寫。我把MyThread寫成了一個匿名的最終的內部類,方便調用。它用了最直接的繼承Thread來實現一個線程類,定義需要運行的run()方法。
首先注釋了print2()方法,看看print1()的結果如何。print1()是一個使用了synchronized關鍵字定義的方法,我一直以為這樣也可以實現線程安全。殊不知,我錯了。
我們來直接運行main()方法。控制臺打印結果如下:
新聞熱點
疑難解答
圖片精選