Java synchronized同步 各方式略解,javasynchronized

來源:互聯網
上載者:User

Java synchronized同步 各方式略解,javasynchronized

  近段為了實現一個功能,在樹結構中,修改某個節點名稱時,需要同時修改這個節點所有子節點的節點全路徑屬性欄位(類似"父父節點名稱/父節點名稱/子節點名稱/子子節點名稱"的構造)。因為在構造Update語句時,需要遞迴去查詢子節點以及構造全路徑的值,需要花費了一定的時間,等批量執行update語句時,可能子節點的某個子節點的名稱又改變了,會引起衝突,故用到了synchronized,順便瞭解了下實現方式,原理沒深入瞭解,在此記錄以便日後查看。

-----------------------------------------------------我是本文分割線--------------------我是本文分割線---------------------------

本文主要列舉不同的同步方式,以及我理解的使用範圍。

眾所周知,同步分為兩種用法:同步方法、與同步塊。

一、同步塊

1.1 類同步(非靜態方法)

· 實現方式:

1 public class JustPlayServiceImplSyn2 { 2 3 public JustPlayServiceImplSyn2(){ 4 5 } 6 private static int flag = 1; 7 public void operate() { 8 synchronized(JustPlayServiceImplSyn2.class){ 9 flag++; 10 try { 11 // 增加隨機性,讓不同線程能在此交替執行 12 Thread.sleep(new Random().nextInt(5)); 13 } catch (InterruptedException e) { 14 e.printStackTrace(); 15 } 16 flag--; 17 System.out.println("Thread: " + Thread.currentThread().getName() 18 + " /Current flag: " + flag);19 }20 }21 }View Code

· 測試代碼:

1 public class JustPlay { 2 /** 3 * @param args 4 */ 5 public static void main(String[] args) { 6 new Thread("Thread-01") { 7 public void run() { 8 new JustPlayServiceImplSyn2().operate(); 9 } 10 }.start(); // 啟動第一個線程11 12 new Thread("Thread-02") { 13 public void run() { 14 new JustPlayServiceImplSyn2().operate();15 } 16 }.start(); // 啟動第一個線程17 }18 }View Code

· 使用範圍:多個物件多線程的同步。
  使用範圍最廣,代碼也簡單,在需要同步的代碼塊上加上synchronized關鍵字,並在括弧類用[類名.class]就行。

1.2 this同步(非靜態方法)

· 實現方式:

1 public class JustPlayServiceImplSyn2 { 2 3 public JustPlayServiceImplSyn2(){ 4 5 } 6 private static int flag = 1; 7 public void operate_this() { 8 synchronized(this){ 9 flag++; 10 try { 11 // 增加隨機性,讓不同線程能在此交替執行 12 Thread.sleep(new Random().nextInt(5)); 13 } catch (InterruptedException e) { 14 e.printStackTrace(); 15 } 16 flag--; 17 System.out.println("Thread: " + Thread.currentThread().getName() 18 + " /Current flag: " + flag);19 }20 }21 }View Code

· 測試代碼:

1 public class JustPlay { 2 3 /** 4 * @param args 5 */ 6 public static void main(String[] args) { 7 final JustPlayServiceImplSyn2 justplayserviceimplsyn2= new JustPlayServiceImplSyn2(); 8 for(int i=0;i<100;i++){ 9 new Thread("Thread-001"){10 public void run() {11 justplayserviceimplsyn2.operate_this();12 }13 }.start();14 new Thread("Thread-002"){15 public void run() {16 justplayserviceimplsyn2.operate_this();17 }18 }.start();19 }20 }View Code

· 使用範圍:單對象多線程的同步。

  在synchronized關鍵字後的括弧內用this關鍵字。使用[this]同步時需要是同一對象的才能同步,多個物件時是同步失敗的。因為同步是對this對象鎖,不同對象時鎖互不影響

 

1.3 靜態對象同步(非靜態方法)

· 實現方式:

1 public class JustPlayServiceImpl { 2 private static JustPlayServiceImpl myobj = null; 3 4 private JustPlayServiceImpl(){ 5 6 } 7 public static JustPlayServiceImpl createJustPlayServiceImpl(){ 8 if(myobj==null){ 9 myobj = new JustPlayServiceImpl();10 }11 return myobj;12 }13 private static int flag = 1;14 public void operate() { 15 synchronized(myobj){16 flag++; 17 try { 18 // 增加隨機性,讓不同線程能在此交替執行 19 Thread.sleep(new Random().nextInt(5)); 20 } catch (InterruptedException e) { 21 e.printStackTrace(); 22 } 23 flag--; 24 System.out.println("Thread: " + Thread.currentThread().getName() 25 + " /Current flag: " + flag);26 }27 }28 }View Code

· 測試代碼:

1 public class JustPlay { 2 3 /** 4 * @param args 5 */ 6 public static void main(String[] args) { 7 8 for(int i=0;i<100;i++){ 9 new Thread("Thread-01") { 10 public void run() { 11 JustPlayServiceImpl.createJustPlayServiceImpl().operate()) } 12 }.start(); // 啟動第一個線程13 new Thread("Thread-02") { 14 public void run() { 15 JustPlayServiceImpl.createJustPlayServiceImpl().operate() } 16 }.start(); // 啟動第二個線程17 }View Code

· 使用範圍:單體類單對象多線程的同步。

  因為同步是對對象的同步鎖,只要保證同步塊對象唯一,就能實現同步。偷點懶,我直接將類變成了單體類,然後將唯一對象給鎖了。(ps:怎麼感覺有點鬼畜。。。哈哈哈)

二、同步方法

2.1 靜態方法同步

· 實現方式:

1 public class JustPlayServiceImplSyn2 { 2 3 public JustPlayServiceImplSyn2(){ 4 5 } 6 private static int flag = 1; 7 public synchronized static void operate_static(){ 8 flag++; 9 try { 10 // 增加隨機性,讓不同線程能在此交替執行 11 Thread.sleep(new Random().nextInt(5)); 12 } catch (InterruptedException e) { 13 e.printStackTrace(); 14 } 15 flag--; 16 System.out.println("Thread: " + Thread.currentThread().getName() 17 + " /Current flag: " + flag);18 }19 }View Code

· 測試代碼:

1 public class JustPlay { 2 3 /** 4 * @param args 5 */ 6 public static void main(String[] args) { 7 for(int i=0;i<100;i++){ 8 new Thread("Thread-01") { 9 public void run() { 10 JustPlayServiceImplSyn2.operate_static();11 } 12 }.start(); // 啟動第一個線程13 14 new Thread("Thread-02") { 15 public void run() { 16 JustPlayServiceImplSyn2.operate_static();17 } 18 }.start(); // 啟動第一個線程19 }20 }21 }View Code

· 使用範圍:靜態方法單對象多線程的同步。

  再次說[因為同步是對對象的同步鎖],而且調用靜態方法綁定的是類而不是對象,所以,同步了靜態方法,就是將相當於將類給鎖了,然後就同步了。原理與[1.1 類同步(非靜態方法)]一致。

2.2 非靜態方法同步

  2.2.1 單體類非靜態方法同步

  ·  實現方式:  

1 public class JustPlayServiceImpl { 2 private static JustPlayServiceImpl myobj = null; 3 4 private JustPlayServiceImpl(){ 5 6 } 7 public static JustPlayServiceImpl createJustPlayServiceImpl(){ 8 if(myobj==null){ 9 myobj = new JustPlayServiceImpl();10 }11 return myobj;12 }13 private static int flag = 1;14 15 //單體類 此種同步方式有效16 public synchronized void operate2() { 17 flag++; 18 try { 19 // 增加隨機性,讓不同線程能在此交替執行 20 Thread.sleep(new Random().nextInt(5)); 21 } catch (InterruptedException e) { 22 e.printStackTrace(); 23 } 24 flag--; 25 System.out.println("Thread: " + Thread.currentThread().getName() 26 + " /Current flag: " + flag);27 }28 }View Code

  · 測試代碼:

1 public static void main(String[] args) { 2 3 for(int i=0;i<100;i++){ 4 new Thread("Thread-01") { 5 public void run() { 6 JustPlayServiceImpl.createJustPlayServiceImpl().operate2(); 7 } 8 }.start(); // 啟動第一個線程 9 10 new Thread("Thread-02") { 11 public void run() { 12 JustPlayServiceImpl.createJustPlayServiceImpl().operate2();13 } 14 }.start(); // 啟動第一個線程15 }16 }17 }View Code

  · 使用範圍:單體類單對象多線程的同步。

    原理同[1.3 靜態對象同步(非靜態方法)]

  2.2.2 非單體類非靜態方法同步

  · 實現方式:

1 public class JustPlayServiceImplSyn2 { 2 3 public JustPlayServiceImplSyn2(){ 4 5 } 6 private static int flag = 1; 7 //適用於單對象多線程 8 public synchronized void operate2() { 9 flag++; 10 try { 11 // 增加隨機性,讓不同線程能在此交替執行 12 Thread.sleep(new Random().nextInt(5)); 13 } catch (InterruptedException e) { 14 e.printStackTrace(); 15 } 16 flag--; 17 System.out.println("Thread: " + Thread.currentThread().getName() 18 + " /Current flag: " + flag);19 }20 }View Code

  · 測試代碼:

1 public class JustPlay { 2 3 /** 4 * @param args 5 */ 6 public static void main(String[] args) { 7 final JustPlayServiceImplSyn2 justplayserviceimplsyn2= new JustPlayServiceImplSyn2(); 8 for(int i=0;i<100;i++){ 9 new Thread("Thread-001"){10 public void run() {11 justplayserviceimplsyn2.operate2();12 }13 }.start();14 new Thread("Thread-002"){15 public void run() {16 justplayserviceimplsyn2.operate2();17 }18 }.start();19 }20 }View Code

  · 使用範圍:單對象多線程的同步。

    原理同[1.2 this同步(非靜態方法)]

總結:對於網頁用ajax方式多次調用的class,因為是多線程且不可控為單一對象,若想同步:解決方案是:1.1、1.3、2.1、2.2.1;對於1.2和2.2.2,調用的對象必須是保持同一個才會同步。

PS:覺得應該還有其他方式,隱隱的這麼覺得。。。。。哈哈哈哈哈哈

------------------------------------結束的分割線--------------結束的分割線------------------有機會再去瞭解同步的底層原理去了----那時候再寫原理------またね!---

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.