java object monitor

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() 方法而阻塞的全部線程一次性所有解除阻塞。固然,只有得到鎖的那一個線程才能進入可執行狀態。

相關文章
相關標籤/搜索