java多執行緒--多執行緒同步
阿新 • • 發佈:2020-07-16
為何要實現同步
java允許多執行緒併發控制,當多個執行緒同時操作一個可共享的資源變數時(如資料的增刪改查), 將會導致資料不準確,相互之間產生衝突,因此加入同步鎖以避免在該執行緒沒有完成操作之前,被其他執行緒的呼叫,從而保證了該變數的唯一性和準確性。
同步程式碼塊
即有synchronized關鍵字修飾的語句塊。
被該關鍵字修飾的語句塊會自動被加上內建鎖,從而實現同步 程式碼如: synchronized(lock){ 操作共享資原始碼塊 } 上面的程式碼中,lock是一個鎖物件,它是同步程式碼塊的關鍵,保證用於處理共享資源的程式碼在任何時刻只能有一個執行緒訪問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()修飾為同步方法,實現了和同步程式碼塊一樣的效果。