Java多線程中的同步機(jī)制會對資源進(jìn)行加鎖,保證同一時刻只有一個線程操作該資源各淀,避免多個線程同時訪問該資源造成沖突。
Synchronized是Java中的同步鎖關(guān)鍵字,主要修飾的對象有:
-
修飾非靜態(tài)方法
同步的是外部調(diào)用的實(shí)例對象父叙,如new Sync()。多線程中不同實(shí)例調(diào)用a(),同步的是不同的Sync實(shí)例趾唱,同步無效屿岂。 -
修飾靜態(tài)方法
同步的是包含此方法的類,如Sync.class鲸匿。多線程中不同實(shí)例調(diào)用b()爷怀,同步的是同一個Sync.class,同步有效带欢。 -
修飾方法塊
同步的對象是synchronized(obj)內(nèi)的非NULL的Object运授。- 若obj為Sync.class,則同步Sync.class本身乔煞,同理synchronized修飾靜態(tài)方法吁朦;
- 若obj為類屬性,如string變量渡贾,則同步的是變量所屬對象實(shí)例逗宜,即是外部調(diào)用的對象實(shí)例。
修飾非靜態(tài)方法示例:
/**
* a()方法是經(jīng)過synchronized修飾的非靜態(tài)方法空骚,同步的是在外部調(diào)用的對象實(shí)例纺讲。
* 由于外部多線程中是不同的對象實(shí)例,則對count的操作未實(shí)現(xiàn)同步(示例現(xiàn)象:未有序遞減)囤屹。
*/
public synchronized void a() {
print();
}
修飾靜態(tài)方法示例:
/**
* b()方法是經(jīng)過synchronized修飾的靜態(tài)方法熬甚,同步的是本類的對象實(shí)例,和外部多線程中的調(diào)用對象實(shí)例無關(guān)肋坚。
* 外部多線程乡括,誰先獲得本類的對象鎖,其他線程則處于阻塞狀態(tài)智厌,直到獲得鎖的線程解鎖诲泌。
*/
public static synchronized void b() {
print();
}
修飾方法塊示例:
/**
* c()和d()是靜態(tài)方法和非靜態(tài)方法的殼,內(nèi)部synchronized修飾的是方法塊铣鹏。
* 同步的對象是synchronized(obj)內(nèi)的非NULL的Object敷扫。
* 1.若obj為Sync.class,則同步Sync.class本身吝沫,同理synchronized修飾靜態(tài)方法呻澜;
* 2.若obj為類屬性,如string變量惨险,則同步的是變量所屬對象實(shí)例羹幸,即是外部調(diào)用的對象實(shí)例。
*/
public void c() {
synchronized (string) {
print();
}
}
public static void d() {
synchronized (Sync.class) {
print();
}
}
外部多線程中不同對象實(shí)例的調(diào)用:
Count.INSTANT.count = 100;
new Thread(() -> new Sync().a()).start();
new Thread(() -> new Sync().a()).start();
print打印操作如下:
public static void print() {
while (Count.INSTANT.count > 0) {
Count.INSTANT.count = Count.INSTANT.count - 1;
Log.d("Sync", "count = " + Count.INSTANT.count);
}
}
單一數(shù)據(jù)源如下:
/**
* 序列化單例模式辫愉,確保操作的是單一數(shù)據(jù)源
*/
public enum Count {
INSTANT;
public int count;
}
補(bǔ)充知識點(diǎn):
- 類的靜態(tài)成員變量和方法栅受,是存儲在方法區(qū)的,使用時均不用創(chuàng)建對象,在類加載初始化后即可使用屏镊。
- 類的非靜態(tài)成員變量在類的實(shí)例化時分配內(nèi)存并初始化依疼,屆時才可調(diào)用。非靜態(tài)成員的值存放在堆區(qū)而芥,其中基本數(shù)據(jù)類型直接保存值律罢,復(fù)雜類型保存指向堆對象的引用。