synchrozied方法和synchrozied修飾代碼塊的區別
阿新 • • 發佈:2018-07-25
tst img 分析 name highlight string targe ack odi
synchroized是jvm提供的,無需手動控制它可以自動對多線程訪問的資源進行加鎖與解鎖,它可以修飾方法,也可以修飾代碼塊.
這邊博客記錄下個人對synchrozied的理解如下:
1.為什麽Java要提供synchronized?
當多條線程去對一個類的實例變量進行修改,這時會發生變量的不確定性.為解決這個問題,使用synchronized修飾,使得在某一時刻,只能有一條線程進行操作.實現的方式是加鎖與解鎖.
2.實例演示多線程訪問共享變量產生的問題.
public class ManyThreadModify implements Runnable{
private int value = 10;
@Override
public void run() {
for(int i = 0; i < 10; i++) {
value--;
System.out.println(Thread.currentThread().getName() + "修改value的值為:" + value);
}
}
public static void main(String[] args) {
ManyThreadModify mm = new ManyThreadModify();
//使用實現Runnable接口的方式可以共享變量,每啟動的線程都是以target形式啟動的
new Thread(mm , "線程01").start();
new Thread(mm , "線程02").start();
}
}
可以看到,出現了value的值兩次等於8的情況,這就是線程不安全造成的,在run方法上加上synchronize修飾可以解決這個問題.
3.synchrozied修飾方法和修飾代碼塊的區別
修飾方法:synchronize public void test(){}
修飾代碼塊:synchronize(鎖對象){ //代碼塊 }
區別:
public class SynchronizedMethodAndCode{ //synchronize修飾方法 public synchronized void test01() { try { System.out.println("this is method test01..."); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } public void test02() { //synchronize修飾代碼塊,鎖對象為當前對象 synchronized (this) { System.out.println("this is method test02..."); } } public void test03() { String str = "s"; //synchronize修飾代碼塊,鎖對象為str synchronized (str) { System.out.println("this is method test03..."); } } }
啟動線程訪問
public class SynchroziedMain { public static void main(String[] args) { SynchronizedMethodAndCode sc = new SynchronizedMethodAndCode(); //啟動線程1訪問test01方法 new Thread(new Runnable() { @Override public void run() { sc.test01(); } }).start(); //啟動線程2訪問test02方法 new Thread(new Runnable() { @Override public void run() { sc.test02(); } }).start(); //啟動線程3訪問test03方法 new Thread(new Runnable() { @Override public void run() { sc.test03(); } }).start(); } }
可以看到打印結果,
分析:啟動線程1訪問test01方法時遇到sleep(3000),線程1沒有釋放鎖資源,在這裏,鎖資源就是當前對象,鎖被線程1拿在了手裏沒有釋放,而test02方法的鎖對象this也是當前對象,所以線程1和線程2使用的是同一把鎖,線程2等待線程1 sleep()結束才能獲得鎖,進入test02方法的打印代碼中,所以線程3先打印了,因為它的鎖是自己定義的一個String對象.
總結:synchronize修飾方法的鎖對象只能是this當前對象
synchronize修飾代碼塊可以修改鎖對象
synchrozied方法和synchrozied修飾代碼塊的區別