多线程访问同步方法的7种情况

如果大家想了解synchronized的信息,可以看我的另外一篇博客:https://blog.csdn.net/killerofjava/article/details/103374409
1.两个线程同时访问一个对象的同步方法。

public class SynchronizedObjectMethod3 implements Runnable {
    static SynchronizedObjectMethod3 soMethod=new SynchronizedObjectMethod3();
    @Override
    public void run() {
       method();
    }
    public synchronized  void method(){
        System.out.println("我的对象锁的方法修饰形式,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }
    public static void main(String[] args) {
        Thread thread01 = new Thread(soMethod);
        Thread thread02 = new Thread(soMethod);
        thread01.start();
        thread02.start();
        while (thread01.isAlive() || thread02.isAlive()){

        }
        System.out.println("finished");
    }
}

结果:
在这里插入图片描述

原因:因为这两个线程用的都是同一个runnable实例,所以它们拿的是同一把对象锁,既然是同一把锁那么它们自然就窜行执行。

2.两个线程访问的是两个对象的同步方法。

public class SynchronizedObjectMethod3 implements Runnable {
    static SynchronizedObjectMethod3 soMethod1=new SynchronizedObjectMethod3();
    static SynchronizedObjectMethod3 soMethod2=new SynchronizedObjectMethod3();
    @Override
    public void run() {
       method();
    }
    public synchronized  void method(){
        System.out.println("我的对象锁的方法修饰形式,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }
    public static void main(String[] args) {
        Thread thread01 = new Thread(soMethod1);
        Thread thread02 = new Thread(soMethod2);
        thread01.start();
        thread02.start();
        while (thread01.isAlive() || thread02.isAlive()){

        }
        System.out.println("finished");
    }
}

结果:
在这里插入图片描述
原因:因为这两个线程用的不是同一个runnable实例,所以它们拿的不是同一把对象锁,既然不是同一把锁,那么它们自然就并行执行。
3.两个线程访问的是synchronized的静态方法

public class SynchronizedClassStatic4 implements  Runnable{
    static SynchronizedClassStatic4 instance1 = new SynchronizedClassStatic4();
    static SynchronizedClassStatic4 instance2 = new SynchronizedClassStatic4();
    @Override
    public void run() {
        method();
    }
    public static  synchronized  void method(){
        System.out.println("我是类锁的第一种形式:static形式,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }
    public static void main(String[] args) {
        Thread thread01 = new Thread(instance1);
        Thread thread02 = new Thread(instance2);
        thread01.start();
        thread02.start();
        while (thread01.isAlive() || thread02.isAlive()){

        }
        System.out.println("finished");
    }
}

结果:
在这里插入图片描述
原因:因为访问的方法被synchronized和static关键字修饰,所以不管是不是用的是同一个runnable实例,它们获得的都是同一把类锁,自然是窜行执行。
4.同时访问同步方法和非同步方法

public class SynchronizedYesOrNo6 implements  Runnable {
    static SynchronizedYesOrNo6 instance = new SynchronizedYesOrNo6();
    @Override
    public void run() {
        if ("Thread-0".equals(Thread.currentThread().getName())){
            method1();
        }else{
            method2();
        }
    }
    public synchronized  void method1(){
        System.out.println("我加锁的方法,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }

    public   void method2(){
        System.out.println("我没加锁的方法,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }
    public static void main(String[] args) {
        Thread thread01 = new Thread(instance);
        Thread thread02 = new Thread(instance);
        thread01.start();
        thread02.start();
        while (thread01.isAlive() || thread02.isAlive()){

        }
        System.out.println("finished");
    }
}

结果:
在这里插入图片描述

原因:因为没有加锁的方法是可以被任何线程访问的,所以它们并行执行。
5.访问同一个对象的不同的普通同步方法。

public class SynchronizedDifferentMethod7 implements Runnable {
    static SynchronizedDifferentMethod7 instance = new SynchronizedDifferentMethod7();
    @Override
    public void run() {
        if ("Thread-0".equals(Thread.currentThread().getName())){
            method1();
        }else{
            method2();
        }
    }
    public synchronized  void method1(){
        System.out.println("我加锁的方法1,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }

    public synchronized   void method2(){
        System.out.println("我加锁的方法2,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }
    public static void main(String[] args) {
        Thread thread01 = new Thread(instance);
        Thread thread02 = new Thread(instance);
        thread01.start();
        thread02.start();
        while (thread01.isAlive() || thread02.isAlive()){

        }
        System.out.println("finished");
    }
}

结果:
在这里插入图片描述

原因:因为用的是同一个runnable实例,所以这两个普通的同步方法用的都是同一把对象锁,自然它们都是窜行执行。

6.同时访问静态synchronized和非synchronized方法。

public class SynchronizedStaticAndNormal8 implements Runnable {
    static SynchronizedStaticAndNormal8 instance = new SynchronizedStaticAndNormal8();
    @Override
    public void run() {
        if ("Thread-0".equals(Thread.currentThread().getName())){
            method1();
        }else{
            method2();
        }
    }
    public static synchronized  void method1(){
        System.out.println("我静态加锁的方法1,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }

    public synchronized   void method2(){
        System.out.println("我非静态加锁的方法2,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }
    public static void main(String[] args) {
        Thread thread01 = new Thread(instance);
        Thread thread02 = new Thread(instance);
        thread01.start();
        thread02.start();
        while (thread01.isAlive() || thread02.isAlive()){

        }
        System.out.println("finished");
    }
}

结果:
在这里插入图片描述
原因;因为获得的锁不同,一个获得的是类锁,二另一个获得的是对象锁,所以它们会并行执行。

7.方法抛出异常后,会释放锁。

public class SynchronizedException9 implements Runnable {
    static SynchronizedException9 instance = new SynchronizedException9();
    @Override
    public void run() {
        if ("Thread-0".equals(Thread.currentThread().getName())){
            method1();
        }else{
            method2();
        }
    }
    public  synchronized  void method1(){
        System.out.println("我加锁的方法1,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        int i=8/0;
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }

    public synchronized  void method2(){
        System.out.println("我加锁的方法2,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }
    public static void main(String[] args) {
        Thread thread01 = new Thread(instance);
        Thread thread02 = new Thread(instance);
        thread01.start();
        thread02.start();
        while (thread01.isAlive() || thread02.isAlive()){

        }
        System.out.println("finished");
    }
}

结果:
在这里插入图片描述
原因:被synchronized关键字修饰的方法在抛出异常后,jvm会自动的帮我们释放锁,不需要我们手动释放锁。我们可以看到在method1()方法抛出异常后,method2()方法立马执行了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值