java多線程開發--語法糖之synchronized關鍵字
介紹
相信接觸過java多線程開發的朋友對於synchronized關鍵詞並不陌生。在java中一切皆對象理念,每個對象都包含一個monitor,用處之一就是在多線程操作時加鎖(lock)解鎖(unlock)。
synchronized關鍵字在聲明之後會定義一個代碼執行段block{},synchronized可以包含參數——synchronized(Object A)
1. 當對象A爲null時,執行synchronized會拋出NullPointerException;
2. 當對象A不爲null時,synchronized會嘗試鎖住(lock)對象A的monitor;
a)如果lock成功,那麼會執行定義的代碼執行段block{},直到退出代碼執行段block{}時調用解鎖(unlock)對象A的monitor;
b)如果lock失敗,那麼說明此時有其他線程佔用對象A的monitor,當前線程會繼續等待直到對象A的monitor空閒lock成功才繼續步驟a)的操作;
當前知道的synchronized有三種使用方式:
1. 顯示指明對象 sychronized(a);
此時synchronized被調用時會使用對象a的monitor;
2. 在類的方法定義中聲明 public synchronized void setter();
此時synchronized被調用時會使用當前對象this的monitor;
3. 在類的靜態方法定義中聲明 public synchronized void setter();
此時synchronized被調用時會使用當前類的class的monitor;
例子
上面文縐縐的概念解釋完了,接下來讓我們用代碼來演示吧;
public class SynchronizedKeyword {
private int number = 0;
public static void main(String args[]) {
SynchronizedKeyword demo = new SynchronizedKeyword();
demo.testUnsynchronized();
demo.number = 0;
demo.testSynchronizedObectMethod();
demo.number = 0;
demo.testSynchronizedStaticMethod();
}
private void processNumber() {
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName() + " number: " + number);
number++;
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private synchronized void processNumber2() {
processNumber();
}
private static synchronized void processNumber3(SynchronizedKeyword target) {
target.processNumber();
}
private void testUnsynchronized() {
System.out.println("testUnsynchronized: 本方法主要測試多線程同步沒有synchronized關鍵字時打印number時的兩個線程同時打印.");
System.out.println("testUnsynchronized-->begin");
Thread t1 = new Thread() {
@Override
public void run() {
processNumber();
}
};
Thread t2 = new Thread() {
@Override
public void run() {
processNumber();
}
};
t1.setName("unsynchronizedTest_t1");
t1.start();
t2.setName("unsynchronizedTest_t2");
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("testUnsynchronized-->end");
}
private void testSynchronizedObectMethod() {
System.out.println("testSynchronizedObjectMethod: 本方法主要測試多線程同步:非靜態方法通過synchronized關鍵字實現多線程先後順序打印number.");
System.out.println("testSynchronizedObjectMethod-->begin");
Thread t1 = new Thread() {
@Override
public void run() {
processNumber2();
}
};
Thread t2 = new Thread() {
@Override
public void run() {
synchronized (SynchronizedKeyword.this) {
processNumber();
}
}
};
t1.setName("testSynchronizedObjectMethod_t1");
t1.start();
t2.setName("testSynchronizedObjectMethod_t2");
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("testSynchronizedObjectMethod-->end");
}
private void testSynchronizedStaticMethod() {
System.out.println("testSynchronizedStaticMethod: 本方法主要測試多線程同步:靜態方法通過synchronized關鍵字實現多線程先後順序打印number.");
System.out.println("testSynchronizedStaticMethod-->begin");
Thread t1 = new Thread() {
@Override
public void run() {
processNumber3(SynchronizedKeyword.this);
}
};
Thread t2 = new Thread() {
@Override
public void run() {
synchronized (SynchronizedKeyword.class) {
processNumber();
}
}
};
t1.setName("testSynchronizedStaticMethod_t1");
t1.start();
t2.setName("testSynchronizedStaticMethod_t2");
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("testSynchronizedStaticMethod-->end");
}
}
輸出結果
testUnsynchronized: 本方法主要測試多線程同步沒有synchronized關鍵字時打印number時的兩個線程同時打印.
testUnsynchronized-->begin
unsynchronizedTest_t1 number: 0
unsynchronizedTest_t2 number: 1
unsynchronizedTest_t2 number: 2
unsynchronizedTest_t1 number: 3
unsynchronizedTest_t1 number: 4
unsynchronizedTest_t2 number: 5
testUnsynchronized-->end
testSynchronizedObjectMethod: 本方法主要測試多線程同步:非靜態方法通過synchronized關鍵字實現多線程先後順序打印number.
testSynchronizedObjectMethod-->begin
testSynchronizedObjectMethod_t1 number: 0
testSynchronizedObjectMethod_t1 number: 1
testSynchronizedObjectMethod_t1 number: 2
testSynchronizedObjectMethod_t2 number: 3
testSynchronizedObjectMethod_t2 number: 4
testSynchronizedObjectMethod_t2 number: 5
testSynchronizedObjectMethod-->end
testSynchronizedStaticMethod: 本方法主要測試多線程同步:靜態方法通過synchronized關鍵字實現多線程先後順序打印number.
testSynchronizedStaticMethod-->begin
testSynchronizedStaticMethod_t1 number: 0
testSynchronizedStaticMethod_t1 number: 1
testSynchronizedStaticMethod_t1 number: 2
testSynchronizedStaticMethod_t2 number: 3
testSynchronizedStaticMethod_t2 number: 4
testSynchronizedStaticMethod_t2 number: 5
testSynchronizedStaticMethod-->end
Process finished with exit code 0