1. 程式人生 > 實用技巧 >java多執行緒--多執行緒同步

java多執行緒--多執行緒同步

為何要實現同步

  java允許多執行緒併發控制,當多個執行緒同時操作一個可共享的資源變數時(如資料的增刪改查), 將會導致資料不準確,相互之間產生衝突,因此加入同步鎖以避免在該執行緒沒有完成操作之前,被其他執行緒的呼叫,從而保證了該變數的唯一性和準確性。 

同步程式碼塊

即有synchronized關鍵字修飾的語句塊。

被該關鍵字修飾的語句塊會自動被加上內建鎖,從而實現同步 程式碼如: synchronized(lock){   操作共享資原始碼塊 }   上面的程式碼中,lock是一個鎖物件,它是同步程式碼塊的關鍵,保證用於處理共享資源的程式碼在任何時刻只能有一個執行緒訪問
注:同步是一種高開銷的操作,因此應該儘量減少同步的內容。 通常沒有必要同步整個方法,使用synchronized程式碼塊同步關鍵程式碼即可。
 1 @SpringBootTest
 2 //Ticket,實現Runnable介面
 3 class Ticket implements Runnable{
 4     //定義變數tickets,並賦值10
 5     private int tickets = 10;
 6     //定義任意一個物件,用作同步程式碼塊的鎖
 7     Object lock = new Object();
 8 
 9     //實現介面中的run()方法
10 @Override 11 public void run() { 12 while (true){ 13 synchronized (lock){ 14 try { 15 Thread.sleep(10); 16 }catch (InterruptedException e){ 17 e.printStackTrace(); 18 } 19 if
(tickets > 0){ 20 System.out.println(Thread.currentThread().getName() + "---賣出的票" + tickets--); 21 }else { 22 //如果tickets 小於0 ,跳出迴圈 23 break; 24 } 25 } 26 } 27 } 28 } 29 public class Example { 30 public static void main(String[] args) { 31 //建立Ticket物件 32 Ticket ticket = new Ticket(); 33 //開啟四個執行緒 34 new Thread(ticket,"執行緒一").start(); 35 new Thread(ticket,"執行緒二").start(); 36 new Thread(ticket,"執行緒三").start(); 37 new Thread(ticket,"執行緒四").start(); 38 } 39 }

執行結果:

  將有關tickets變數的操作全部都放到同步程式碼塊中,為了保證執行緒的持續執行,將同步程式碼塊放在死迴圈中,直到tickets<0時跳出迴圈,持續在獲得鎖物件時有一定的隨機性,在整個程式的執行期間,執行緒二和執行緒三始終未獲得鎖物件。

同步方法

  在方法面前同樣可以使用synchronized關鍵字來修飾,被修飾的方法為同步方法,它能實現和同步程式碼塊同樣的功能。

具體語法格式:

  

 1 @SpringBootTest
 2 //Ticket,實現Runnable介面
 3 class Ticket implements Runnable{
 4     //定義變數tickets,並賦值10
 5     private int tickets = 10;
 6 
 7     //實現介面中的run()方法
 8     public void run() {
 9        while (true){
10            saleTicket(); //呼叫售票方法
11            if (tickets <=0){
12                break;
13            }
14        }
15 
16     }
17     //定義一個同步方法saleTicket
18     private synchronized void saleTicket(){
19         if (tickets > 0){
20             try {
21                 Thread.sleep(100);
22             }catch (InterruptedException e){
23                 e.printStackTrace();
24             }
25             System.out.println(Thread.currentThread().getName() + "賣出的票 --" + tickets --);
26         }
27     }
28 }
29 public class Example {
30     public static void main(String[] args) {
31         //建立Ticket物件
32         Ticket ticket = new Ticket();
33         //開啟四個執行緒
34         new Thread(ticket,"執行緒一").start();
35         new Thread(ticket,"執行緒二").start();
36         new Thread(ticket,"執行緒三").start();
37         new Thread(ticket,"執行緒四").start();
38     }
39  }

執行結果:

  將售票程式碼抽取為售票方法saleTicket(),並用synchronized關鍵字把saleTicket()修飾為同步方法,實現了和同步程式碼塊一樣的效果。