[Java] synchronized在代码块中修饰.class与this的区别

Posted luffy5459

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Java] synchronized在代码块中修饰.class与this的区别相关的知识,希望对你有一定的参考价值。

    synchronized是java中的关键字,表示同步,可以在多线程环境中起到锁的作用。它是jvm层面的锁,不需要人为获取释放锁资源,由jvm决定。

    synchronized可以直接用在方法上,这种用法和synchronized在代码块中修饰this是一样的。

    synchronized也可以直接用在static静态方法上,这种用法和synchronized在代码块中修饰.class类似,说类似是因为代码块粒度更小一些。

    它也可以用在代码块中,这时候它可以修饰一个类对象.class,一个全局对象lock,或者this。

     一般我们关注的就是修饰.class和this的区别。

     修饰.class,就是表示多线程调用该类的不管什么实例,所有实例共用一把锁。

     修饰this,多线程调用该类的实例,如果每个线程都有一个实例,那么每个实例都有各自的锁,他们互相不影响。如果多线程去竞争一个实例,那么这个锁就只有一把,多线程去争一个资源。

    下面通过一个示例来看看他们的区别:

package com.xxx.lock;
import java.util.Date;
public class SynchronizedExample 
    public static void main(String[] args) 
        for(int i=0;i<5;i++)
            BusinessService businessService = new BusinessService();
            new BusinessThread(businessService).start();
        
    

    static class BusinessService
        public void action()
            synchronized (BusinessService.class)
                try 
                    System.out.println(Thread.currentThread().getName()+" running at "+new Date());
                    Thread.sleep(1000);
                catch (Exception e)
                    e.printStackTrace();
                

            
        
    

    static class BusinessThread extends Thread
        BusinessService businessService;
        public BusinessThread(BusinessService businessService)
            this.businessService = businessService;
        

        @Override
        public void run() 
            businessService.action();
        
    

    运行结果:

Thread-0 running at Mon Oct 10 22:32:49 CST 2022
Thread-4 running at Mon Oct 10 22:32:50 CST 2022
Thread-3 running at Mon Oct 10 22:32:51 CST 2022
Thread-2 running at Mon Oct 10 22:32:52 CST 2022
Thread-1 running at Mon Oct 10 22:32:53 CST 2022

    从结果可以看出,多线程调用synchronized(.class)修饰的代码块时,无论线程调用的对象实例是一个,还是多个,最终只有一个线程进入同步代码块。其他线程等待资源释放再运行。

    这个地方,如果synchronized修饰this:

    结果是这样的:

Thread-3 running at Mon Oct 10 22:37:41 CST 2022
Thread-2 running at Mon Oct 10 22:37:41 CST 2022
Thread-4 running at Mon Oct 10 22:37:41 CST 2022
Thread-1 running at Mon Oct 10 22:37:41 CST 2022
Thread-0 running at Mon Oct 10 22:37:41 CST 2022

    五个线程几乎同时执行,因为他们各自调用的是不同的实例,而每个实例都有自己的锁,与其他实例互不干扰。

    这个代码其实可以修改,就是线程创建的时候,指定对象实例为同一个。

    这个时候运行结果就是多线程竞争一把锁,线程依次交替执行:

Thread-0 running at Mon Oct 10 22:50:23 CST 2022
Thread-4 running at Mon Oct 10 22:50:24 CST 2022
Thread-3 running at Mon Oct 10 22:50:25 CST 2022
Thread-2 running at Mon Oct 10 22:50:26 CST 2022
Thread-1 running at Mon Oct 10 22:50:27 CST 2022

    这个时候,把synchronized修饰符改为修饰.class,结果也是一样的,线程交替执行。

    从上面的示例,我们可以知道,要想多线程竞争一把锁,我们使用synchronized修饰.class、this都是可以的,但是在使用this的时候,需要注意,如果我们传递给线程的实例各不相同,那么最终同步代码块之间互不干扰 ,就没有同步的作用了。

以上是关于[Java] synchronized在代码块中修饰.class与this的区别的主要内容,如果未能解决你的问题,请参考以下文章

java 多线程9 : synchronized锁机制 之 代码块锁

[Java] synchronized在代码块中修饰.class与this的区别

java中,用synchronized会锁定当前对象,这个对象指的是它包涵的代码块,还是一个类实例

JAVA多线程synchronized详解

java synchronized详解

java synchronized详解