多线程访问 synchronized 方法的八种具体情况

本文深入探讨Java中线程同步的多种情形,包括不同线程访问同步与非同步方法的效果,静态同步方法的锁定机制,以及异常处理对锁的影响。通过具体示例代码,清晰展示各种场景下线程的执行顺序,帮助理解Java并发编程的核心概念。

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

概述

  • 情况一:两个线程同时访问一个对象synchronized 方法,同步执行;
  • 情况二:两个线程访问的是两个对象synchronized 方法,并行执行;
  • 情况三:两个线程同时访问一个 synchronized 静态方法,同步执行;
  • 情况四:两个线程同时访问 synchronized 方法非 synchronized 方法,并发执行;
  • 情况五:两个线程同时访问同一个对象不同 synchronized 方法,同步执行;
  • 情况六:两个线程同时访问静态 synchronized 方法非静态 synchronized 方法,并行执行;
  • 情况七:方法抛异常后,会释放锁
  • 情况八:在 synchronized 方法中调用了普通方法,就不是线程安全的了,synchronized 的作用范围只在 “{}” 内;

示例四 - 同时访问同步方法与非同步方法

package com.example.concurrency.example.sync;

public class SynchronizedYesAndNo4 implements Runnable {

    static SynchronizedYesAndNo4 instance = new SynchronizedYesAndNo4();

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

    public synchronized void method1() {
        System.out.println(Thread.currentThread().getName() + " 访问 synchronized mothod1() 开始");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " 访问 synchronized mothod1() 结束");
    }

    public void method2() {
        System.out.println(Thread.currentThread().getName() + " 访问 mothod2() 开始");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " 访问 mothod2() 结束");
    }

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

        t1.start();
        t2.start();

        while (t1.isAlive() || t2.isAlive()) {

        }
        System.out.println(Thread.currentThread().getName() + " 结束");
    }

}

输出:

Thread-0 访问 synchronized mothod1() 开始
Thread-1 访问 mothod2() 开始
Thread-0 访问 synchronized mothod1() 结束
Thread-1 访问 mothod2() 结束
main 结束

示例五 - 两个线程同时访问同一个对象的不同 synchronized 方法

package com.example.concurrency.example.sync;

public class SynchronizedYesAndNo5 implements Runnable {

    static SynchronizedYesAndNo5 instance = new SynchronizedYesAndNo5();

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

    public synchronized void method1() {
        System.out.println(Thread.currentThread().getName() + " 访问 synchronized mothod1() 开始");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " 访问 synchronized mothod1() 结束");
    }

    public synchronized void method2() {
        System.out.println(Thread.currentThread().getName() + " 访问 synchronized mothod2() 开始");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " 访问 synchronized mothod2() 结束");
    }

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

        t1.start();
        t2.start();

        while (t1.isAlive() || t2.isAlive()) {

        }
        System.out.println(Thread.currentThread().getName() + " 结束");
    }

}

输出:

Thread-0 访问 synchronized mothod1() 开始
Thread-0 访问 synchronized mothod1() 结束
Thread-1 访问 synchronized mothod2() 开始
Thread-1 访问 synchronized mothod2() 结束
main 结束

示例六 - 两个线程同时访问静态 synchronized 方法和非静态 synchronized 方法

package com.example.concurrency.example.sync;

public class SynchronizedYesAndNo6 implements Runnable {

    static SynchronizedYesAndNo6 instance = new SynchronizedYesAndNo6();

    @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() + " 访问 synchronized static mothod1() 开始");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " 访问 synchronized static mothod1() 结束");
    }

    public synchronized void method2() {
        System.out.println(Thread.currentThread().getName() + " 访问 synchronized mothod2() 开始");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " 访问 synchronized mothod2() 结束");
    }

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

        t1.start();
        t2.start();

        while (t1.isAlive() || t2.isAlive()) {

        }
        System.out.println(Thread.currentThread().getName() + " 结束");
    }

}

输出:

Thread-1 访问 synchronized mothod2() 开始
Thread-0 访问 synchronized static mothod1() 开始
Thread-1 访问 synchronized mothod2() 结束
Thread-0 访问 synchronized static mothod1() 结束
main 结束

示例七 - 方法抛异常后,会释放锁

package com.example.concurrency.example.sync;

public class SynchronizedYesAndNo7 implements Runnable {

    static SynchronizedYesAndNo7 instance = new SynchronizedYesAndNo7();

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

    public synchronized void method1() {
        System.out.println(Thread.currentThread().getName() + " 访问 synchronized static mothod1() 开始");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        throw new RuntimeException();
    }

    public synchronized void method2() {
        System.out.println(Thread.currentThread().getName() + " 访问 synchronized mothod2() 开始");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " 访问 synchronized mothod2() 结束");
    }

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

        t1.start();
        t2.start();

        while (t1.isAlive() || t2.isAlive()) {

        }
        System.out.println(Thread.currentThread().getName() + " 结束");
    }

}

输出:

Thread-0 访问 synchronized static mothod1() 开始
Exception in thread "Thread-0" java.lang.RuntimeException
Thread-1 访问 synchronized mothod2() 开始
    at com.example.concurrency.example.sync.SynchronizedYesAndNo7.method1(SynchronizedYesAndNo7.java:23)
    at com.example.concurrency.example.sync.SynchronizedYesAndNo7.run(SynchronizedYesAndNo7.java:10)
    at java.lang.Thread.run(Thread.java:745)
Thread-1 访问 synchronized mothod2() 结束
main 结束
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值