java 静态同步锁static synchronized详解

下面我们看例子1:

有一个phone类,里面有两个同步方法(synchronized修饰),分别为发送email和发送短信,在main方法中实例化一部手机,开启两个线程去操作phone这个资源类

public class Phone {

    public synchronized void sendMail() throws Exception {
        TimeUnit.SECONDS.sleep(4);
        System.out.println("******sendMail******");
    }
    public synchronized void sendSMS() throws Exception {
        System.out.println("******sendSMS*******");
    }

    public static void main(String[] args) throws InterruptedException {
        Phone phone = new Phone();
        new Thread(()->{
            try {
                phone.sendMail();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"A").start();
        Thread.sleep(100);
        new Thread(()->{
            try {
                phone.sendSMS();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"B").start();
    }
}

输出结果:

java 静态同步锁static synchronized详解_第1张图片

在等待4s后,输出以上结果,这是为什么呢?如果一个对象里面有多个synchronized方法,某一时刻内,只要一个线程去调用synchronized方法,其他线程只能等待,换句话说,只能有唯一一个线程去访问这些synchronized方法,锁的是当前对象this,被锁定后,其他线程都不能进入到当前对象的其他synchronized方法,如果是普通方法则不影响访问。

如果新实例化一个phone2 去执行发短信的操作,则结果如下:

这是因为两个对象互不影响,synchronized是对象锁。

java 静态同步锁static synchronized详解_第2张图片

例子2:

有一个phone类,里面有两个静态同步方法(static synchronized修饰),分别为发送email和发送短信,在main方法中实例化一部手机,开启两个线程去操作phone这个资源类

public class Phone {

    public static synchronized void sendMail() throws Exception {
        TimeUnit.SECONDS.sleep(4);
        System.out.println("******sendMail******");
    }
    public static synchronized void sendSMS() throws Exception {
        System.out.println("******sendSMS*******");
    }

    public static void main(String[] args) throws InterruptedException {
        Phone phone = new Phone();
        new Thread(()->{
            try {
                phone.sendMail();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"A").start();
        Thread.sleep(100);
        new Thread(()->{
            try {
                phone.sendSMS();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"B").start();
    }
}

输出结果:

java 静态同步锁static synchronized详解_第3张图片

如果实例化phone2再去执行发短信操作,则结果和上面一样。这是因为经过static修饰过后,这个锁变为全局锁,锁的是这个类的模板(Class文件),所以不管有几个实例化对象,都要等待模板锁释放下一个线程才能进行操作。

例子3:

有一个phone类,里面有一个同步方法一个静态同步方法,在main方法中实例化一部手机,开启两个线程去操作phone这个资源类

public class Phone {

    public static synchronized void sendMail() throws Exception {
        TimeUnit.SECONDS.sleep(4);
        System.out.println("******sendMail******");
    }
    public synchronized void sendSMS() throws Exception {
        System.out.println("******sendSMS*******");
    }

    public static void main(String[] args) throws InterruptedException {
        Phone phone = new Phone();
        new Thread(()->{
            try {
                phone.sendMail();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"A").start();
        Thread.sleep(100);
        new Thread(()->{
            try {
                phone.sendSMS();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"B").start();
    }
}

输出结果:

java 静态同步锁static synchronized详解_第4张图片

这是因为静态同步锁和非静态同步方法之间不会有竞争条件,这两把锁是两个不同的对象,锁的本质一个是锁对象,一个是锁Class模板类;一个静态同步方法获得锁后,其他的静态同步方法都必须等待该方法释放锁后才能获取锁。

你可能感兴趣的:(Java多线程)