1 什麼是java object monitorhtml
每一個java對象頭中都有鎖狀態位標記。java中在使用synchronize同步的時候,確定是涉及到某個對象的鎖。所以,在考慮同步的時候,首先要想到是同步的是哪一個對象的鎖。java
在java字節碼上,獲取了某個對象的鎖以後,進入時會調用monitorenter指令,在退出時會調用monitorexit指令。編程
可見,java object monitor是對java對象的鎖的一種抽象。它和java對象是一對一的關係的。ide
在java中,經過java object monitor使得鎖是和其保護的對象一一對應的。函數
2 關於synchronized關鍵字線程
它能夠用來修飾普通方法,靜態方法和修飾代碼段。orm
修飾普通方法的時候,使用的monitor就是類對應的對象的鎖。htm
修飾代碼段的時候,使用的monitor也是類對象的對象的鎖。對象
而修飾靜態方法時,使用的monitor是類的class對象的鎖,這樣的monitor只有一個。blog
具體能夠參考下面的博文:
http://www.cnblogs.com/paddix/p/5367116.html
3 爲何「只有擁有該對象的monitor的線程才能夠調用該對象的wait()、notify()和notifyAll()方法」?
由於wait()、notify()和notifyAll()是object monitor提供的函數,在語義上,沒有擁有該monitor的線程是不能調用它們的。java經過拋出異常來
保證程序在用法上知足這個語義。
4 爲何「wait/notify」方法必需要在synchronized的方法或者段中調用呢?
由於只有進入了synchronized方法或者方法段中的線程才擁有了該鎖對象,只有擁有了該鎖對象才能調用該鎖對象的wait和notify方法。
5 下面的代碼在wait以後呢?被喚醒以後,是接着wait後面的執行嗎?
synchronized (object) {
while (<condition does not hold>)
object.wait();
// perform actions to condition
}
是的,被喚醒以後,它又從新獲取了該鎖以後,就會接着wait後面的執行。
例子:
public class Test {
public static Object object = new Object();
public static void main(String[] args) {
Thread1 thread1 = new Thread1();
Thread2 thread2 = new Thread2();
thread1.start();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread2.start();
}
static class Thread1 extends Thread{
@Override
public void run() {
synchronized (object) {
try {
object.wait();
} catch (InterruptedException e) {
}
System.out.println("線程"+Thread.currentThread().getName()+"獲取到了鎖");
}
}
}
static class Thread2 extends Thread{
@Override
public void run() {
synchronized (object) {
object.notify();
System.out.println("線程"+Thread.currentThread().getName()+"調用了object.notify()");
System.out.println("線程"+Thread.currentThread().getName()+"釋放了鎖");
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("同步塊外的邏輯"+Thread.currentThread().getName());
}
}
}
先打印Thread1中要打印的內容,而後再打印Thread2中要打印的內容。
6 notify()和notifyAll()的使用
第一:調用 notify() 方法致使解除阻塞的線程是從因調用該對象的 wait() 方法而阻塞的線程中隨機選取的,咱們沒法預料哪個線程
將會被選擇,因此編程時要特別當心,避免因這種不肯定性而產生問題。
第二:除了 notify(),還有一個方法 notifyAll() 也可起到相似做用,惟一的區別在於,調用 notifyAll() 方法將把因調用該對象的
wait() 方法而阻塞的全部線程一次性所有解除阻塞。固然,只有得到鎖的那一個線程才能進入可執行狀態。