synchronized 修饰在 static方法和非static方法的区别

本文深入探讨了Java中synchronized关键字用于静态方法与非静态方法时的不同表现,通过代码示例展示了类锁与对象锁的区别,并提出了使用Lock实现类下所有方法共用同一把锁的方法。

Java中synchronized用在静态方法和非静态方法上面的区别

在Java中,synchronized是用来表示同步的,我们可以synchronized来修饰一个方法。也可以synchronized来修饰方法里面的一个语句块。那么,在static方法和非static方法前面加synchronized到底有什么不同呢?大家都知道,static的方法属于类方法,它属于这个Class(注意:这里的Class不是指Class的某个具体对象),那么static获取到的锁,是属于类的锁。而非static方法获取到的锁,是属于当前对象的锁。所以,他们之间不会产生互斥。

上代码

package TestSynchronizedStaticOrNot;

public class TestSynchronizedStaticOrNot {

    public static synchronized void staticFunction(String name)
            throws InterruptedException {
        for (int i = 0; i < 3; i++) {
            Thread.sleep(1000);
            System.out.println(name + " --- static function running ...");
        }
    }

    public synchronized void function(String name) throws InterruptedException {
        for (int i = 0; i < 3; i++) {
            Thread.sleep(1000);
            System.out.println(name + " +++ function running ...");
        }
    }

    public static void main(String[] args) {

        final TestSynchronizedStaticOrNot demo = new TestSynchronizedStaticOrNot();

        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    staticFunction("1");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread thread11 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    staticFunction("2");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    demo.function("1");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread thread23 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    demo.function("12");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread thread22 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    new TestSynchronizedStaticOrNot().function("2");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        thread11.start();
        thread1.start();
        thread2.start();
        thread23.start();
        thread22.start();
    }
}

这里写图片描述

根据结果很容分析到,加在类上面的锁,加载对象上面的锁。如果上了对象锁,同一个对象是不能再获取锁的,必须等待释放,如果是不同的实例还是可以去获取锁的。

那当我们想让所有这个类下面的方法都同步的时候,也就是让所有这个类下面的静态方法和非静态方法共用同一把锁的时候,我们如何办呢?此时我们可以使用Lock。

`synchronized` 关键字用于控制线程对共享资源的访问,确保在任一时刻只有一个线程能执行该代码块或方法。在 Java 中,将 `synchronized` 修饰静态方法静态(实例)方法会带来一些不同: 1. 静态同步 (synchronized static): - 当在静态方法上使用 `synchronized` 时,是对当前类(Class 对象)的引用,而不是具体的对象实例。这意味着所有对该类的调用都会共享同一把,无论它们来自哪个对象。 - 因此,如果两个不同的线程同时持有这个类的静态,那么只有其中一个能够执行静态同步的方法。 - 好处在于简化了定管理,因为不需要为每个实例创建独立的。但这也意味着线程之间的可见性状态一致性可能不像基于实例的同步那么容易理解。 2. 实例同步 (synchronized on instance): - 在实例方法上使用 `synchronized`,是该方法所在的对象实例。每个调用该方法的具体对象都会获得自己的,所以并发地调用相同方法的不同对象是可以并行执行的。 - 这有助于维护每个对象的状态独立性,但需要更精确地管理,尤其是当多个方法需要互斥访问同一个实例变量时。 - 如果一个类的所有实例都需要同步,那通常使用静态更为合适,因为静态更容易管理避免死。 总结一下,关键区别在于: - 静态同步适用于类级别的资源共享,所有对象共享一把; - 实例同步针对单个对象,每个实例有自己的,适合处理特定对象的数据并发操作。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值