java同步機制物件鎖使用方式比較
class Sync { private byte[] lock = new byte[0]; public void sync() throws InterruptedException { synchronized (lock) { runThread(); } } public void thisSync() throws InterruptedException { synchronized (this) { runThread(); } } public synchronized static void staticSync() throws InterruptedException { // 同步的static 函式 runThread(); } public void classSync() throws InterruptedException { // synchronized (Sync.class) { runThread(); } } private static void runThread() throws InterruptedException { Thread current = Thread.currentThread(); System.out.println("current thread id:" + current.getId() + "enter..."); System.out.println("1111"); Thread.sleep(1000); System.out.println("2222"); Thread.sleep(1000); System.out.println("3333"); Thread.sleep(1000); System.out.println("4444"); Thread.sleep(1000); System.out.println("5555"); System.out.println("current thread id:" + current.getId() + "out..."); } }
1.同一個執行緒lock物件鎖是否可複用(即不用等待)
結論:可複用
public class TestObjectSyncLock { private static byte[] lock = new byte[0];//零長度的byte陣列物件建立起來將比任何物件都經濟――檢視編譯後的位元組碼:生成零長度的byte[]物件只需3條操作碼,而Object lock = new Object()則需要7行操作碼。 public static void main(String[] args) throws InterruptedException { //1.同一個執行緒lock物件鎖是否可複用(即不用等待)----可複用 synchronized (lock) { new Thread(new Runnable() { public void run() { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("aaa"); } }).start(); // lock.notify(); } synchronized (lock) { System.out.println("bbb"); // lock.wait(); } } }
結果:
bbb
aaa
2.同一個物件,多執行緒訪問(一個主執行緒,一個新開執行緒)
結論:鎖有效
Thread current = Thread.currentThread(); System.out.println("current thread id:"+current.getId()+"start..."); final Sync sync =new Sync(); new Thread(new Runnable() { public void run() { Thread current = Thread.currentThread(); System.out.println("current thread id:"+current.getId()+"start..."); try { sync.sync(); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); sync.sync();
結果:
current thread id:1start...
current thread id:1enter...
1111
current thread id:9start...
2222
3333
4444
5555
current thread id:1out...
current thread id:9enter...
1111
2222
3333
4444
5555
current thread id:9out...
3.不同物件,多執行緒訪問
結論:鎖無效
Thread current = Thread.currentThread();
System.out.println("currret thread id:" + current.getId() + "start...");
final Sync sync = new Sync();
final Sync sync2 = new Sync();
new Thread(new Runnable() {
public void run() {
Thread current = Thread.currentThread();
System.out.println("currret thread id:" + current.getId() + "start...");
try {
sync2.sync();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
sync.sync();
結果:
currret thread id:1start...
current thread id:1enter...
1111
currret thread id:9start...
current thread id:9enter...
1111
2222
2222
3333
3333
4444
4444
5555
current thread id:1out...
5555
current thread id:9out...
4.wait(),notify()----呼叫wait或notify時,該執行緒必須是該物件鎖的所有者,否則會丟擲Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
new Thread(new Runnable() {
public void run() {
System.out.println("------");
synchronized (lock) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.notify();
System.out.println(" after notify ...");
}
}
}).start();
synchronized (lock) {
System.out.println("enter ...");
lock.wait();
System.out.println("out ...");
}
結果:
enter ...
------
after notify ...
out ...
5.wait(),notifyAll()----notifyAll()喚醒所有正在wait的不同執行緒
new Thread(new Runnable() {
public void run() {
synchronized (lock) {
System.out.println("enter thread 1 ...");
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("leave thread 1 ...");
}
}
}).start();
new Thread(new Runnable() {
public void run() {
synchronized (lock) {
System.out.println("enter thread 2 ...");
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("leave thread 2 ...");
}
}
}).start();
new Thread(new Runnable() {
public void run() {
System.out.println("------");
synchronized (lock) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.notifyAll();// notifyAll方法會喚醒所有正在等待物件控制權的執行緒。
// lock.notify();//隨機通知一個正在等待的執行緒
System.out.println("after notifyAll ...");
}
}
}).start();
結果:
enter thread 1 ...
enter thread 2 ...
------
after notifyAll ...
leave thread 2 ...
leave thread 1 ...
6.static 同步方法,不同物件
Thread current = Thread.currentThread();
System.out.println("currret thread id:" + current.getId() + "start...");
Sync sync = new Sync();
new Thread(new Runnable() {
public void run() {
Sync sync = new Sync();
Thread current = Thread.currentThread();
System.out.println("currret thread id:" + current.getId() + "start...");
try {
sync.staticSync();// 鎖有效
// Sync.staticSync();//鎖有效
// sync.sync();//鎖無效
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
sync.staticSync();// 鎖有效
// Sync.staticSync();//鎖有效
// sync.sync();//鎖無效
結果:
currret thread id:1start...
current thread id:1enter...
1111
currret thread id:9start...
2222
3333
4444
5555
current thread id:1out...
current thread id:9enter...
1111
2222
3333
4444
5555
current thread id:9out...
7.class 同步方法,不同物件
Thread current = Thread.currentThread();
System.out.println("currret thread id:" + current.getId() + "start...");
Sync sync = new Sync();
new Thread(new Runnable() {
public void run() {
Sync sync = new Sync();
Thread current = Thread.currentThread();
System.out.println("currret thread id:" + current.getId() + "start...");
try {
sync.classSync();// 鎖有效
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
sync.classSync();// 鎖有效
結果:
currret thread id:1start...
current thread id:1enter...
1111
currret thread id:9start...
2222
3333
4444
5555
current thread id:1out...
current thread id:9enter...
1111
2222
3333
4444
5555
current thread id:9out...
8.this 同步方法,不同物件,跟2一樣,物件鎖
final Sync sync = new Sync();
new Thread(new Runnable() {
public void run() {
// Sync sync =new Sync();
Thread current = Thread.currentThread();
System.out.println("currret thread id:" + current.getId() + "start...");
try {
sync.thisSync();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
public void run() {
// Sync sync =new Sync();
Thread current = Thread.currentThread();
System.out.println("currret thread id:" + current.getId() + "start...");
try {
sync.thisSync();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
結果:
currret thread id:9start...
current thread id:9enter...
1111
currret thread id:10start...
2222
3333
4444
5555
current thread id:9out...
current thread id:10enter...
1111
2222
3333
4444
5555
current thread id:10out...