Java—多线程4—monitor机制

本文介绍了Java中的对象锁(monitor)机制,包括同步代码块和同步方法的实现原理,强调了锁的可冲入性和互斥性。通过示例证明了在同一时刻只有一个线程能持有锁,以及锁的可重入特性,即同一线程可以多次进入已持有的锁保护的代码段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java—多线程4—monitor机制

##对象锁(monitor)

同步代码块:

执行同步代码块后首先执行monitorenter指令,退出时执行monitorexit指令

使用内建锁(synchronize)实现同步,关键在于要获取指定对象monitor监视器,当线程获取monitor后才继续向下执行,否则就只能等待。这个过程是互斥的,每个时刻只能有一个线程获取对象的monitor。

通常一个monitor指令会包含若干个monitorexit指令,原因是JVM需要确保锁在正常执行路径和在异常执行路径上都可以正常的解锁。

同步方法:当使用synchronize修饰方法时,编译后的字节码中访问标记多了一个ACC_SYNCHRONIZE。该标记表示,进入该方法时,JVM均需要进行monitorenter操作,退出该方法时,无论正常返回,JVM均需要进行monitorexit操作。

锁的获取过程:

当执行monitorenter时,如果目标锁对象的monitor计数器为0,表示此对象没有被任何其他锁持有。此时JVM会将锁持有线程设置为当前线程,并将计数器加1;如果目标计数器不为0,判断锁持有的线程是否是当前线程,如果是计数器再次加1(锁的可重入性)。如果所对象的持有线程不是当前线程,当前线程需要等待,直至持有线程释放锁。

锁的释放过程:

当执行monitorexit时,JVM会将对象计数器-1.当技术器减为0时,代表该对象已经被释放。

证明锁的可冲入性和互斥性:

可重入:

class MyThread implements Runnable{

    @Override
    public void run() {
        test1();
    }
    public synchronized  void test1(){
        if(Thread.currentThread().getName().equals("A")){
            System.out.println("A线程进入test1方法");
        }
            teat2();
    }
    public  synchronized void teat2(){

            System.out.println(Thread.currentThread().getName()+"进入test2方法");
    }
}
public class Test{
    public static void main(String[] args) {
        MyThread mt=new MyThread();
        new Thread(mt,"A").start();
    }
}


互斥性:

class MyThread implements Runnable{

    @Override
    public void run() {
        test1();
        teat2();
    }
    public synchronized  void test1(){
        if(Thread.currentThread().getName().equals("A")){
            while(true){}
        }
    }
    public  synchronized void teat2(){
        if(Thread.currentThread().getName().equals("B")){
         System.out.println("线程B进入同步方法2");
        }else{
        System.out.println(Thread.currentThread().getName()+"进入test2方法");
        }


    }
}
public class Test{
    public static void main(String[] args) {
        MyThread mt=new MyThread();
        new Thread(mt,"A").start();
        //-------确保A线程先启动-------
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //----------------------------
       new Thread(mt,"B").start();
    }
}


互斥性:同一时刻只有一个线程持有锁:

线程A,进入test1,线程B:不能进入test2

上面的代码让线程A先进入,然后循环,

如果线程B可以进入test2,那么就会打印"线程B进入同步方法2"

但是事实上 线程一直处于阻塞状态,没有进入代码块。

上一篇 Java内建锁

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值