這篇文章我們簡單了解下java中實例鎖和類鎖。
在這里先給個福利,惡補下鎖的作用:對于并發(fā)工作,你需要某種方式來防止兩個任務(wù)訪問相同的資源(其實就是共享資源競爭)。 防止這種沖突的方法就是當(dāng)資源被一個任務(wù)使用時,在其上加鎖。第一個訪問某項資源的任務(wù)必須鎖定這項資源,使其他任務(wù)在其被解鎖之前,就無法訪問它了,而在其被解鎖之時,另一個任務(wù)就可以鎖定并使用它了。
下面進入正題:
實例鎖:對一個類的一個實例對象(對象A)進行加鎖,防止其他線程同時訪問對象A的synchronized塊,但是對不同的此類的實例對象不做控制。實例鎖使用Synchronized關(guān)鍵字修飾。
類鎖:對一個類的所有實例對象進行加鎖,限制多線程中該類的所有實例同時訪問該類的synchronized塊。類鎖使用Static Synchronized關(guān)鍵字修飾。
文字比較生澀,我們看看代碼:
實例鎖
package com.xingshulin;
public class ObjectSyncTest implements Runnable {
int salary = 0;
public void run(){
addSalary();
}
public synchronized void addSalary() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
salary += 1;
System.out.println(salary);
}
public static void main(String[] args) {
ObjectSyncTest st = new ObjectSyncTest();
for (int i = 0; i < 10; i++) {
new Thread(st).start();
}
}
}
返回結(jié)果:
1
2
3
4
5
6
7
8
9
10
Process finished with exit code 0
代碼很簡單,我們可以看到addSalary方法是使用synchronized修飾的,所以它是實例鎖。在main函數(shù)中我們使用了一個對象st,并生成了10個線程對st對象中的變量salary進行+1操作,可以看到最終結(jié)果確實是同步的。
有些童鞋會問了,那我要是把synchronized關(guān)鍵字去掉呢?其實這就是線程安全的問題了,在這里不多說,但是我們可以看下去掉后的返回值:
5
7
9
9
6
6
9
8
4
7
Process finished with exit code 0
很明顯不對了是吧,再多試幾遍,雖然每次得到的結(jié)果都不同,但是很明顯都是不對的。這就是因為沒有加同步鎖,在程序運行中產(chǎn)生了線程沖突。
類鎖
package com.xingshulin;
public class ClassSyncTest implements Runnable {
public static int salary = 0;
public void run(){
addSalary();
}
public static synchronized void addSalary() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
salary += 1;
System.out.println(salary);
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
ClassSyncTest st = new ClassSyncTest();
new Thread(st).start();
}
}
}
返回結(jié)果:
1
2
3
4
5
6
7
8
9
10
Process finished with exit code 0
結(jié)合實例鎖的代碼來看,對比很明顯了。代碼中addSalary方法是使用static synchronized關(guān)鍵字修飾的,所以它是類鎖。而在main函數(shù)中使用了10個不同的對象st,每個對象都對變量salary進行+1操作,可以看到最終結(jié)果也是同步的。
為了證明確實類鎖管用,我們把static關(guān)鍵字刪掉(變成了實例鎖),這樣再跑下程序:
3
3
3
4
8
8
9
5
6
7
Process finished with exit code 0
很明顯,線程又沖突了,所以也正好證明了實例鎖只能管自己的一個實例,對于類中的所有實例是無法做到同步的。