Java多執行緒中Synchronized簡介和Static Synchronized的區別
在進行Java開發時,多執行緒的開發是經常會使用的。首先會問一個小問題啊,在Java中有幾種方法可以建立一個執行緒?
我給的答案是3種。(如果還有其他的請留言告訴我哈。)
1、建立直接繼承自Thread類建立執行緒子類。
步驟如下:a 定義一個子類,同時要繼承Thread類。
b 在這個子類中重寫run方法。
c 在需要的地方建立該子類的例項,即建立一個執行緒例項。
d 呼叫start方法來啟動執行緒。
2、建立實現Runnable介面的類。
步驟如下:a 定義一個類,並且實現了Runnable介面。
b 在子類中實現介面的run方法,並且重寫run方法。
c 建立該子類的一個例項,並將該例項作為引數傳入到
d 最後呼叫執行緒的start方法來啟動執行緒。即t1.start()。
3、對於應用程式可以使用Excutor框架來建立執行緒。主要是使用Callable介面和Future介面。其中Callable介面和Runnable介面很像,但Callable介面會更加的抽象,而
接下來來說說執行緒同步的問題,既然出現了多執行緒的概念。那我們就要注意了,當執行緒A使用一個變數或者一段程式碼的時候 ,我們要確保其他的執行緒不能干擾到執行緒A。這種情況下,就出現了執行緒同步的概念。就是執行緒A在使用一個變數或者一段程式碼的時候,其他的執行緒必須等待。直到執行緒A不需要了,其他的執行緒才會去競爭。
舉個形象的例子啊,火車車廂洗手間的問題。當有人A在使用車廂洗手間的時候,其他的人只能在外面等待。當A出來了,其他的人才會按照排隊的順序進去。這裡A之所以可以放心的使用洗手間是因為洗手間裡有鎖。那麼在多執行緒中出現的執行緒鎖就需要關鍵字Synchronized來表示。
現在我們來說說Synchronized關鍵字。當Synchronized修飾某個方法的時候,那麼就稱這個方法為同步方法。當Synchronized修飾某個程式碼塊的時候,那麼就程這段程式碼為同步程式碼塊。如下:
這是同步方法:
public Synchronized void A(){
}
這是同步程式碼塊:
......
Synchronized(Object){ //注意Object被稱為鎖物件
........ //這裡面的就是同步的程式碼塊
}
..........
好了,到這裡我們知道了Synchronized關鍵字的用途了。但是經常會有人看到Static Synchronized的出現。這個和Synchronized有什麼區別呢。
Synchronized(例項鎖):鎖在每一個物件上。如果該類是一個單例(比如單例模式),那麼它就具有全域性鎖的概念。
Static Synchronized(全域性鎖):該鎖針對的是類的,無論例項化了多少個物件,那麼執行緒都是共享這個鎖的。
例子如下:
public Class Something{
public synchronized void sysA(){ }
public synchronized void sysB(){ }
public static synchronized void C_sysA(){ }
public static synchronized void C_sysB(){ }
}
現在假如Something有兩個例項x和y,下面我們來分析下面幾種情況獲取鎖的結果:
(1)x.sysA()和x.sysB()
(2)x.sysA()和y.sysB()
(3)x.C_sysA()和y.C_sysB()
(4)x.sysA()和Something.C_sysA()
現在我們一一分析:
1、這兩個方法是不能同時被呼叫的,因為使用的是同一個物件鎖x。
2、這兩個方法是可以同時被呼叫的,因為使用的不是同一個物件鎖。
3、這兩個方法是不能同時被呼叫的。因為C_sysA()和C_sysB()都使用的是全域性鎖。而x和y是屬於同一個類(Something),所以這兩個方法是共用一個鎖的。
4、這兩個方法是可以同時執行的。首先sysA()方法使用的是物件鎖x,而C_sysA()方法使用的是類的鎖。所以使用的鎖是不一樣的。
到這,文章結束了。希望本篇文章會讓你對於Synchronized關鍵字有更深的理解和認識。