1.靜態(tài)同步Synchronized方法與Synchronized(class)代碼塊:關(guān)鍵字Synchronized還可以應(yīng)用在static靜態(tài)方法上迂烁,如果這樣寫恭陡,那是對當(dāng)前的*.java文件對應(yīng)的Class類進(jìn)行持鎖勋功。class鎖和對象鎖的區(qū)別就在于class鎖可以對所有對象實例起作用坦报。
但是如果兩個方法都被Synchronized修飾一個是靜態(tài)另一個是動態(tài),那么在這種情況下狂鞋,只有一個對象實例時片择,多個線程調(diào)用兩個方法不是同步的。因為調(diào)用兩個方法一個持有對象鎖另一個持有Class鎖骚揍。
Class鎖對所有實例對象起作用體現(xiàn)在构回,當(dāng)有不同線程持有不同實例對象時,執(zhí)行Synchronized修飾的靜態(tài)方法仍然同步。
2.同步Synchronized(class)代碼塊的作用其實和Synchronized static方法作用一樣纤掸。
3.在JVM中具有String常量池緩存功能脐供。數(shù)據(jù)類型String的常量池特性:將Synchronized(string)同步塊與String聯(lián)合使用時,要注意常量池以帶來的一些例外借跪。代碼如下:
public class Service{
public static void print(String stringParam){
try {
synchronized (stringParam){
while (true){
System.out.println(Thread.currentThread().getName());
Thread.sleep(1000);
}
}
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
public class ThreadA extends Thread{
private Service service;
public ThreadA(Service service){
super();
this.service = service;
}
@Override
public void run(){
service.print("AA");
}
}
public class ThreadB extends Thread{
private Service service;
public ThreadB(Service service){
super();
this.service = service;
}
@Override
public void run(){
service.print("AA");
}
}
public static void main(String[] args){
Service service = new Service();
ThreadA a = new ThreadA(service);
a.setName("A");
a.start();
ThreadB b = new ThreadB(service);
b.setName("B");
b.start();
}
以上代碼執(zhí)行時B線程不能執(zhí)行政己,因為String的兩個值都是AA。兩個線程持有相同的鎖掏愁,所以造成線程B不能執(zhí)行歇由。這就是String常量池所帶來的問題。因為在大多數(shù)情況下果港,同步synchronized代碼塊都不使用String作為鎖對象沦泌,而改用其他,比如new Object實例化一個Object對象辛掠,但它并不放入緩存中谢谦。
4.死鎖:同步方法容易造成死鎖。Java線程死鎖是一個經(jīng)典的多線程問題萝衩,因為不同的線程都在等待根本不可能被釋放的鎖回挽,從而導(dǎo)致所有的任務(wù)都無法繼續(xù)完成。在多線程技術(shù)中猩谊,“死鎖”是必須避免的千劈,因為這會造成線程假死。
死鎖是程序設(shè)計的Bug牌捷,在設(shè)計程序時就要避免雙方互相持有對方法的鎖的情況墙牌。需要說明的是不只是使用synchronized才會形成死鎖,不使用synchronized也會形成死鎖暗甥。
如何檢測死鎖憔古?進(jìn)入JDK的安裝文件夾中的bin目錄,執(zhí)行jps命令淋袖,得到運行的線程Run的id值是3244鸿市。再執(zhí)行jstack命令察看結(jié)果是否有死鎖現(xiàn)象。
5.內(nèi)置類和內(nèi)置靜態(tài)類:內(nèi)置類中被synchronized修飾的同步方法所持有的對象的監(jiān)視器是該內(nèi)部類即碗。
6.鎖對象的改變:將任何數(shù)據(jù)類型作為同步鎖時焰情,需要注意的是,是否有多個線程同時持有鎖對象剥懒,如果同時持有相同的鎖對象内舟,則這些線程之間就是同步的,之后即使對象的屬性改變了初橘,也還是同步的验游;如果分別獲得鎖對象充岛,這些線程之間就是異步的。