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

1、两个线程同时访问一个对象的同步方法

public class SynchroizedObject extends Thread{

    static SynchroizedObject instance = new SynchroizedObject();
    public static  void main(String []args) {
        Thread t1 = new Thread(instance);
        Thread t2 = new Thread(instance);
        t1.start();
        t2.start();
    }

    @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()+"运行结束");
    }
}

运行结果:

我的对象锁的方法修饰符形式,我叫Thread-1
Thread-1运行结束
我的对象锁的方法修饰符形式,我叫Thread-2
Thread-2运行结束

同一个实例使用同一把锁,两个线程使用同一把锁,必然有一个处于等待,一个线程执行完成,另一个线程才可以执行。

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

public class SynchroizedObject2 extends Thread{

    static SynchroizedObject2 instance1 = new SynchroizedObject2();
    static SynchroizedObject2 instance2 = new SynchroizedObject2();

    public static  void main(String []args) {
        Thread t1 = new Thread(instance1);
        Thread t2 = new Thread(instance2);
        t1.start();
        t2.start();
    }

    @Override
    public void run() {
        synchronized (this) {
            System.out.println("我的对象锁的方法修饰符形式,我叫"+Thread.currentThread().getName());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"运行结束");
        }
    }


}

运行结果:

我的对象锁的方法修饰符形式,我叫Thread-2
我的对象锁的方法修饰符形式,我叫Thread-3
Thread-2运行结束
Thread-3运行结束

结果线程同时开始,同时结束,之间不会受干扰,因为对象不是同一个,所以不会受干扰。

3、两个线程访问的是synchronize 的静态方法

public class SynchroizedObject3 extends Thread{

    static SynchroizedObject3 instance1 = new SynchroizedObject3();
    static SynchroizedObject3 instance2 = new SynchroizedObject3();

    public static  void main(String []args) {
        Thread t1 = new Thread(instance1);
        Thread t2 = new Thread(instance2);
        t1.start();
        t2.start();
    }

    @Override
    public void run() {
        method();
    }

    public static synchronized void method () {
        System.out.println("我的对象锁的方法修饰符形式,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }


}

运行结果

我的对象锁的方法修饰符形式,我叫Thread-2
Thread-2运行结束
我的对象锁的方法修饰符形式,我叫Thread-3
Thread-3运行结束

只要方法是静态的,锁对应的就是一把,所以线程是一个执行完成,再去执行下一个线程。

4、同时访问同步方法与非同步方法

public class SynchroizedObject4 implements Runnable {

    static SynchroizedObject4 instance = new SynchroizedObject4();

    public static  void main(String []args) {
        Thread t1 = new Thread(instance);
        Thread t2 = new Thread(instance);
        t1.start();
        t2.start();
    }

    @Override
    public void run() {
        if (Thread.currentThread().getName().equals("Thread-0")) {
            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()+"运行结束");
    }

}

运行结果

我的加锁的方法修饰符形式,我叫Thread-0
我的没加锁的方法修饰符形式,我叫Thread-1
Thread-1运行结束
Thread-0运行结束

线程0和线程1几乎同时开始同时结束,synchronized  关键字只作用于指定的method1方法中,没有加上synchronized  这个关键字方法,不受影响,不会由于其他方法加上synchronized  而受到影响。非同步方法不受到影响。

5、访问一个对象的不同的普通同步方法

public class SynchroizedObject5 implements Runnable {

    static SynchroizedObject5 instance = new SynchroizedObject5();

    public static  void main(String []args) {
        Thread t1 = new Thread(instance);
        Thread t2 = new Thread(instance);
        t1.start();
        t2.start();
    }

    @Override
    public void run() {
        if (Thread.currentThread().getName().equals("Thread-0")) {
            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 synchronized void method2() {
        System.out.println("我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }

}

运行结果

我叫Thread-0
Thread-0运行结束
我叫Thread-1
Thread-1运行结束

同一个实例中,这两个方法没有办法同时运行,会出现串行的情况。

6、同时访问静态synchronize和非静态synchronize方法

public class SynchroizedObject6 implements Runnable {

    static SynchroizedObject6 instance = new SynchroizedObject6();

    public static  void main(String []args) {
        Thread t1 = new Thread(instance);
        Thread t2 = new Thread(instance);
        t1.start();
        t2.start();
    }

    @Override
    public void run() {
        if (Thread.currentThread().getName().equals("Thread-0")) {
            method1();
        } else {
            method2();
        }
    }

    public synchronized static void method1() {
        System.out.println("我是静态加锁方法,我叫"+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("非静态加锁方法,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }

}

运行结果

我是静态加锁方法,我叫Thread-0
非静态加锁方法,我叫Thread-1
Thread-0运行结束
Thread-1运行结束

运行结果几乎同时运行,同时结束,所指定的锁对象不是同一个锁,所以可以同时运行。

7、方法抛异常,会释放锁

方法抛异常后,会释放锁。展示不抛出异常前和抛出异常后的对比:一旦抛出了异常,第二个线程会立刻进入同步方法,意味着锁已经释放。

public class SynchroizedObject7 implements Runnable {

    static SynchroizedObject7 instance = new SynchroizedObject7();

    public static  void main(String []args) {
        Thread t1 = new Thread(instance);
        Thread t2 = new Thread(instance);
        t1.start();
        t2.start();
    }

    @Override
    public void run() {
        if (Thread.currentThread().getName().equals("Thread-0")) {
            method1();
        } else {
            method2();
        }
    }

    public synchronized void method1() {
        System.out.println(" 我是静态加锁方法,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } 
        throw new RuntimeException();
//        System.out.println(Thread.currentThread().getName()+"运行结束");
    }

    public synchronized void method2() {
        System.out.println(" 非静态加锁方法,我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }

}

运行结果

我是静态加锁方法,我叫Thread-0
 非静态加锁方法,我叫Thread-1
Exception in thread "Thread-0" java.lang.RuntimeException
	at com.test5.SynchroizedObject7.method1(SynchroizedObject7.java:39)
	at com.test5.SynchroizedObject7.run(SynchroizedObject7.java:25)
	at java.lang.Thread.run(Thread.java:748)
Thread-1运行结束

抛出异常之后,不需要手动手动释放锁,由jvm进行释放锁。

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值