synchronized

修饰代码块

public class LockDemo1 {
    private Object object = new Object();

    public void testMonitor() {
        synchronized (object) {
            System.out.println("Monitor");
        }
    }
}

javap -c LockDemo1 反编译该类

在这里插入图片描述

monitorenter代表获取锁
monitorexit代表释放锁

synchronized修饰代码块是使用 monitorenter 和 monitorexit 来实现锁的获取和释放。默认情况下monitorexit 会有2个:一个正常退出,一个异常退出。
当发生异常时,只会触发第二个monitorexit

修饰实例方法

public class MySynchronized extends  Thread{
    public static void main(String[] args) {
        MyClass myClass=new MyClass();
        MyThread1 myThread1=new MyThread1(myClass);
        MyThread2 myThread2=new MyThread2(myClass);
        myThread1.start();
        myThread2.start();
    }
}

class MyClass{
    public synchronized void hello(){
        try {
            TimeUnit.MILLISECONDS.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Hello");
    }
    public synchronized void world(){
        System.out.println("world");
    }
}

class MyThread1 extends Thread{
    private MyClass myClass;

    public MyThread1(MyClass myClass) {
        this.myClass = myClass;
    }
    @Override
    public void run() {
        myClass.hello();
    }
}

class MyThread2 extends Thread{
    private MyClass myClass;

    public MyThread2(MyClass myClass) {
        this.myClass = myClass;
    }
    @Override
    public void run() {
        myClass.world();
    }
}

打印

Hello
world

改进方法

public class MySynchronized extends  Thread{
    public static void main(String[] args) {
        MyClass myClass1=new MyClass();
        MyClass myClass2=new MyClass();
        MyThread1 myThread1=new MyThread1(myClass1);
        MyThread2 myThread2=new MyThread2(myClass2);
        myThread1.start();
        myThread2.start();
    }
}
-------------------------其余代码不变
打印
world
Hello

1.synchronized 修饰的实例方法相当于是对象锁,锁的是对象
2.当synchronized 修饰普通方法的时候,如果有多线程来访问同一对象的方法,那么同一时刻只能拥有一个线程获取到该对象的锁,也就是意味着:同一时刻只有一个线程在在执行,其他的线程处于等待状态.

在这里插入图片描述

修饰普通方法是通过字节码中的flags来标记的,如果flags中包含了ACC_SYNCHRONIZED,
那么JVM在执行时就知道这是一个同步方法,在调用时就会首先获取到该对象的Monitor对象.
其他线程则不能再获取Monitor对象,并陷入等待状态.直到该方法执行完并释放Monitor锁以后
其他线程才可以获取到该锁

修饰静态方法

public class MySynchronized extends  Thread{
    public static void main(String[] args) {
        MyClass myClass1=new MyClass();
        MyClass myClass2=new MyClass();
        MyThread1 myThread1=new MyThread1(myClass1);
        MyThread2 myThread2=new MyThread2(myClass2);
        myThread1.start();
        myThread2.start();
    }
}

class MyClass{
    public synchronized static void hello(){
        try {
            TimeUnit.MILLISECONDS.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Hello");
    }
    public synchronized static void world(){
        System.out.println("world");
    }
}

class MyThread1 extends Thread{
    private MyClass myClass;

    public MyThread1(MyClass myClass) {
        this.myClass = myClass;
    }
    @Override
    public void run() {
        myClass.hello();
    }
}

class MyThread2 extends Thread{
    private MyClass myClass;

    public MyThread2(MyClass myClass) {
        this.myClass = myClass;
    }
    @Override
    public void run() {
        myClass.world();
    }
}

打印

Hello
world

如果synchronized修饰的是静态方法,那么锁定的是类,该Class对象被所有的对象共享

在这里插入图片描述

修饰j静态方法是通过字节码中的flags来标记的,如果flags中包含了ACC_STATIC,ACC_SYNCHRONIZED,
那么JVM在执行时就知道这是一个J静态的同步方法,在调用时就会首先获取到Class对象的Monitor对象.
其他线程则不能再获取Monitor对象,并陷入等待状态.直到该方法执行完并释放Monitor锁以后
其他线程才可以获取到该锁

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值