synchronized作用域总结

synchronized 关键字代表这个方法加锁,相当于不管哪一个线程(例如线程A),运行到这个方法时,都要检查有没有其它线程B(或者C、 D等)正在用这个方法(或者该类的其他同步方法),有的话要等正在使用synchronized方法的线程B(或者C 、D)运行完这个方法后再运行此线程A,没有的话,锁定调用者,然后直接运行。
本文主要介绍synchronized的用法及作用域。

修饰代码块

大括号括起来的代码,作用于调用的对象

public class SyncTest {

    public void test1(int j) {
        synchronized (this){
            for(int i = 0; i < 20; i++) {
                System.out.println("test:" + j);
            }
        }
    }

    public static void main(String[] args) {
        SyncTest syncTest1 = new SyncTest();
        ExecutorService executorService = Executors.newCachedThreadPool();

        executorService.execute(() -> syncTest1.test1(1));
        executorService.execute(() -> syncTest1.test1(2));
    }
}

在demo中开了两个线程调用同一个对象中的synchronized代码块,输出为先打印第一个线程的输出,在打印第二个线程的输出。

public class SyncTest {

    public void test1(int j) {
        synchronized (this){
            for(int i = 0; i < 20; i++) {
                System.out.println("test:" + j);
            }
        }
    }

    public static void main(String[] args) {
        SyncTest syncTest1 = new SyncTest();
        SyncTest syncTest2 = new SyncTest();
        ExecutorService executorService = Executors.newCachedThreadPool();

        executorService.execute(() -> syncTest1.test1(1));
        executorService.execute(() -> syncTest2.test1(2));
    }
}

在demo中开了两个线程调用不同实列的synchronized代码块,输出为第一个线程,第二个线程交替执行。

结论

对比可以得出synchronized修饰代码块作用域为在一个对象中

修饰方法

整个方法,作用于调用的对象

public class SyncTest {

    public synchronized void test(int j) {
        for (int i = 0; i < 20; i++) {
            System.out.println("test:" + j);
        }
    }

    public static void main(String[] args) {
        SyncTest syncTest1 = new SyncTest();
        ExecutorService executorService = Executors.newCachedThreadPool();

        executorService.execute(() -> syncTest1.test(1));
        executorService.execute(() -> syncTest1.test(2));
    }
}

在demo中开了两个线程调用同一个对象中的synchronized修饰的方法,输出为先打印第一个线程的输出,在打印第二个线程的输出。

public class SyncTest {

    public synchronized void test(int j) {
        for (int i = 0; i < 20; i++) {
            System.out.println("test:" + j);
        }
    }

    public static void main(String[] args) {
        SyncTest syncTest1 = new SyncTest();
        SyncTest syncTest2 = new SyncTest();
        ExecutorService executorService = Executors.newCachedThreadPool();

        executorService.execute(() -> syncTest1.test(1));
        executorService.execute(() -> syncTest2.test(2));
    }
}

在demo中开了两个线程调用不同实列的synchronized修饰的方法,输出为第一个线程,第二个线程交替执行。
注意:父类中定义了synchronized修饰的方法,由子类继承时,需要在子类显示指定synchronized修饰。synchronized不属于方法声明的一部分,不能被继承。

结论

对比可以得出,synchronized修饰的方法作用域为在一个对象中。

修饰静态方法

整个静态方法,作用于所有对象

public class SyncTest {

    public void test(int j) {
       print(j);
    }

    public static synchronized void print(int j){
        for (int i = 0; i < 20; i++) {
            System.out.println("test:" + j);
        }
    }

    public static void main(String[] args) {
        SyncTest syncTest1 = new SyncTest();
        SyncTest syncTest2 = new SyncTest();
        ExecutorService executorService = Executors.newCachedThreadPool();

        executorService.execute(() -> syncTest1.test(1));
        executorService.execute(() -> syncTest2.test(2));
    }
}

执行demo,两个线程顺序执行,可以得出synchronized修饰的静态方法作用域为所有对象。

修饰类

括号括起来的部分,作用于所有对象

public class SyncTest {

    public void test(int j) {
       synchronized (SyncTest.class){
           for(int i = 0; i < 10; i++) {
               System.out.println("test-" + j);
           }
       }
    }


    public static void main(String[] args) {
        SyncTest syncTest1 = new SyncTest();
        SyncTest syncTest2 = new SyncTest();
        ExecutorService executorService = Executors.newCachedThreadPool();

        executorService.execute(() -> syncTest1.test(1));
        executorService.execute(() -> syncTest2.test(2));
    }
}

执行demo,两个线程顺序执行,可以得出synchronized修饰类作用域为所有对象。

总结

修饰代码块:大括号括起来的代码,作用于调用的对象。
修饰方法:整个方法,作用于调用的对象。
修饰静态方法:整个静态方法,作用于所有对象。
修饰类:括号括起来的部分,作用于所有对象。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 13,805评论 1 32
  • 本文出自 Eddy Wiki ,转载请注明出处:http://eddy.wiki/interview-java.h...
    eddy_wiki阅读 6,618评论 0 14
  • 一:java概述:1,JDK:Java Development Kit,java的开发和运行环境,java的开发工...
    ZaneInTheSun阅读 7,597评论 0 11
  • 一、基础知识:1、JVM、JRE和JDK的区别:JVM(Java Virtual Machine):java虚拟机...
    杀小贼阅读 7,048评论 0 4
  • 因为某些原因,前些天给已经离校的同学们发了一个通知。符合某些条件的同学可以领取一千的补贴,但是需要提供一些证明材料...
    倏云阅读 2,767评论 5 5