美文网首页java锁
synchronized作用域总结

synchronized作用域总结

作者: 董二弯 | 来源:发表于2019-12-15 17:42 被阅读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修饰类作用域为所有对象。

    总结

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

    相关文章

      网友评论

        本文标题:synchronized作用域总结

        本文链接:https://www.haomeiwen.com/subject/alnknctx.html