同步關鍵詞synchronized


概述

synchronized是java中的一個關鍵字,也就是說是Java語言內置的特性。

synchronized( 一個任意的對象(鎖) ){
代碼塊中放操作共享數據的代碼。

}

 1 public synchronized int getIndex() {
 2         return 1;
 3     }
 4     
 5     public static synchronized int getNext() {
 6         return 2;
 7     }
 8     
 9     
10     public int getPre() {
11         
12         //這里的參數可以用java所有對象
13         //synchronized(this) {
14         //synchronized(Demo1.class) {
15         synchronized(new Demo1()) {
16             System.out.println("synchronized(這里的參數可以用java所有對象)");
17         }
18         
19         return 0;
20     }

synchronized 放在普通方法上,內置鎖就是當前類的實例。

synchronized 放在靜態方法上,內置鎖就是當前類的Class字節碼對象

如果一個代碼塊被synchronized修飾了,當一個線程獲取了對應的鎖,並執行該代碼塊時,其他線程便只能一直等待,等待獲取鎖的線程釋放鎖。這種特性又被稱為互斥鎖

而這里獲取鎖的線程釋放鎖只會有兩種情況:
1)獲取鎖的線程執行完了該代碼塊,然后線程釋放對鎖的占有。
2)線程執行發生異常,此時JVM會讓線程自動釋放鎖。

實例

繼續賣火車票的例子。

在《Java中Runnable和Thread的區別》火車票例子里,我們看到三個窗口賣出去的火車票,順序是亂的。

如何使順序有序呢?

線程執行的時候,一個個執行不就有序了。即線程1在執行的時候,其他線程阻塞不要執行。

加synchronize。

 1 package multithreading.sync;
 2  
 3 public class MyThreadWithImplements implements Runnable {
 4  
 5     private int tickets = 10;
 6  
 7     @Override
 8     public synchronized void run() {
 9  
10         for (int i = 0; i <= 100; i++) {
11             if(tickets>0){
12                 System.out.println(Thread.currentThread().getName()+"--賣出票:" + tickets--);
13             }
14         }
15     }
16     
17     
18     public static void main(String[] args) {
19         
20         MyThreadWithImplements myRunnable = new MyThreadWithImplements();
21         Thread thread1 = new Thread(myRunnable, "窗口一");
22         Thread thread2 = new Thread(myRunnable, "窗口二");
23         Thread thread3 = new Thread(myRunnable, "窗口三");
24  
25         thread1.start();
26         thread2.start();
27         thread3.start();
28     }
29  
30 }

運行結果

窗口一--賣出票:10
窗口一--賣出票:9
窗口一--賣出票:8
窗口一--賣出票:7
窗口一--賣出票:6
窗口一--賣出票:5
窗口一--賣出票:4
窗口一--賣出票:3
窗口一--賣出票:2
窗口一--賣出票:1

缺陷

例子1

如果這個獲取鎖的線程由於要等待IO或者其他原因(比如調用sleep方法)被阻塞了,但是又沒有釋放鎖,其他線程便只能干巴巴地等待,這多么影響程序執行效率。

因此就需要有一種機制可以不讓等待的線程一直無期限地等待下去(比如只等待一定的時間或者能夠響應中斷),通過Lock就可以辦到。

例子2

當有多個線程讀寫文件時,讀寫操作會發生沖突現象,寫寫操作會發生沖突現象,但是讀讀操作不會發生沖突現象。
但是采用synchronized關鍵字來實現同步的話,就會導致一個問題:
如果多個線程都只是進行讀操作,當一個線程在進行讀操作時,其他線程只能等待無法進行讀操作。

 

因此就需要一種機制來使得多個線程都只是進行讀操作時,線程之間不會發生沖突,通過Lock就可以辦到。
另外,通過Lock可以知道線程有沒有成功獲取到鎖。這個是synchronized無法辦到的。
總的來說,也就是說Lock提供了比synchronized更多的功能。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM