JAVA基础-synchronized

本文详细解析了Java中的synchronized关键字在实现线程同步时的不同应用场景,包括类实例对象锁、类锁、代码块锁及重入锁等,并通过具体示例说明了锁的互斥原理。

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

  

目录

一、类实例对象锁

1.1 采用线程方式,用线程调用每个方法

1.2 synchronized同时修饰method1和method2

二、类锁

三、类的代码块锁(略)

四、类的重入锁

结论:


   在Java类中,有线程安全与不安全之分。线程安全的类在同一时刻,多个线程操作类方法时,需要保证只有一个线程进行操作。synchronized关键字的出现,可以保证共享资源在同一时刻被一个线程操作。

    synchronized关键字在线程同步时,主要有下面三种情况:

  1. 类实例对象锁;

  2. 类锁;

  3.对类的代码块加锁;

  4. 类的重入锁

一、类实例对象锁

public class MyObject {
    public  synchronized void method1(){
        try{
            System.out.println(Thread.currentThread().getName());
            Thread.sleep(4000);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }

    public  void method2(){
        System.out.println(Thread.currentThread().getName());
    }
}

 在上面类中,使用synchronized修饰method1,method2为普通方法。在调用方式上,也有几种不同的情况

1.1 采用线程方式,用线程调用每个方法

    public static void main(String[] args) {
        final MyObject mo = new MyObject();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                mo.method1();
            }
        },"t1");

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                mo.method2();
            }
        },"t2");
        t1.start();
        t2.start();
    }

结果:采用线程调用各自方法,虽然使用的同一个类实例对象,但是调用方法之间不会进行锁等待,即同时执行。

1.2 synchronized同时修饰method1和method2

结果:这种情况下,由于两个方法都进行了同步操作,当某一个线程调用一个方法时即获取了该对象的对象锁,另外一个线程调用时则会进行锁等待。

结论:在同一个实例对象下,采用不同线程调用synchronized方法和非同步方法不会产生锁等待。当两个方法同时被synchronized修饰,则共享同一个对象锁,会产生锁等待。

二、类锁

类锁,即对类进行加锁,常常使用static synchronized来修饰方法。如:

public class MyObject {
    public static synchronized void method1(){
        try{
            System.out.println(Thread.currentThread().getName());
            Thread.sleep(4000);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }

    public synchronized void method2(){
        System.out.println(Thread.currentThread().getName());
    }
}

如上所示:static synchronized修饰method1, synchronized修饰method2。

结果:

(1) 通过1.1代码中不同线程调用method1和method2时,不会产生锁互斥。因为static修饰method1方法属于类方法,而method2属于实例对象方法,二者归属于不同的锁,因此不会产生锁等待。

(2) 当static synchronized同时修饰method1和method2时,方法调用会产生互斥,此时共享的是类锁。  

三、类的代码块锁(略)

四、类的重入锁

synchronized的锁具有重入功能,它共享一个类实例的锁。当一个线程得到一个对象锁后,若再次请求此对象是可以再次得到该对象的锁。如:

public class SyncRepeat {

    public synchronized void method1(){
        System.out.println("method1..");
        method2();
    }

    public synchronized void method2(){
        System.out.println("method2..");
        method3();
    }

    public synchronized void method3(){
        System.out.println("method3..");
    }
}

结果:当线程调用method1时,不存在锁等待,他们得到的都是同一个对象的锁。同时当某个类具有同步方法parent1,而子类继承该类的同时具有method2的同步方法,当method2调用parent1时,不会产生锁互斥。

五、结论

 本文主要分析了synchronized关键字在对象锁与类锁方面的不同情况。对于同一个实例对象,通过线程调用同步和非同步方法,不会产生锁互斥,如果同时调用同步方法则产生互斥。对于static修饰的类锁来说,调用static synchronized方法和synchronized方法时,由于方法二者的锁归属不同,不会产生锁等待。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值