java锁

synchronized作用域总结

2019-12-15  本文已影响0人  董二弯

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修饰类作用域为所有对象。

总结

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

上一篇下一篇

猜你喜欢

热点阅读