• 关于“关键字synchronized不能被继承”的一点理解


    网上看到很多对关键字synchronized继承性的描述只有一句"关键字synchronized不能被继承",并没有描述具体场景,于是自己做了以下测试。

    //父类

    public class Super {

        static Logger logger = Logger.getLogger(Super.class);

        // 同步方法
        @SuppressWarnings("static-access")
        public synchronized void testMothed() {
             try {
                    Thread.currentThread().sleep(5000);//休眠5秒。
             } catch (InterruptedException e) {
                    e.printStackTrace();
             }
              logger.info(Thread.currentThread().getName() + "," + this);
        }

    }

    //子类1

    public class Sub1 extends Super {

        // 不重写父类的同步方法
    }

    //子类2

    public class Sub2 extends Super {

        // 重写父类的同步方法,但不加synchronized。

       @SuppressWarnings("static-access")
        public void testMothed() {
            try {
                   Thread.currentThread().sleep(3000);//为区别与父类中休眠时间,改为3秒。
            } catch (InterruptedException e) {
                      e.printStackTrace();
            }
            logger.info(Thread.currentThread().getName() + "," + this);
        }
    }

    //测试类

    public class SynchronizedTest {

        static Logger logger = Logger.getLogger(SynchronizedTest.class);

        public static void main(String[] args) throws Exception {
                // 子类对象1
                final Sub1 sub1 = new Sub1();
                final int count = 5;
                // 创建count个不同线程,调用子类对象1同一方法
                for (int i = 0; i < count; i++) {
                       new Thread() {
                               public void run() {
                                      sub1.testMothed();
                               }
                        }.start();
                  }

                 // 让上面所有子线程有足够时间执行结束
                 TimeUnit.SECONDS.sleep((count+1)*5);

                  logger.info("===============================================");

                 // 子类对象2
                 final Sub2 sub2 = new Sub2();
                 // 创建count个不同线程,调用子类对象2同一方法
                 for (int i = 0; i < count; i++) {
                         new Thread() {
                              public void run() {
                                   sub2.testMothed();
                             }
                         }.start();
                  }
        }
       
    }

    执行结果:

     12:40:18,043 [INFO]----> Thread-0,java_lang.thread_synchronized.Sub1@86f241
     12:40:23,044 [INFO]----> Thread-4,java_lang.thread_synchronized.Sub1@86f241
     12:40:28,044 [INFO]----> Thread-3,java_lang.thread_synchronized.Sub1@86f241
     12:40:33,044 [INFO]----> Thread-2,java_lang.thread_synchronized.Sub1@86f241
     12:40:38,045 [INFO]----> Thread-1,java_lang.thread_synchronized.Sub1@86f241
     12:40:43,044 [INFO]----> ===============================================
     12:40:46,045 [INFO]----> Thread-6,java_lang.thread_synchronized.Sub2@15dfd77
     12:40:46,045 [INFO]----> Thread-7,java_lang.thread_synchronized.Sub2@15dfd77
     12:40:46,045 [INFO]----> Thread-5,java_lang.thread_synchronized.Sub2@15dfd77
     12:40:46,046 [INFO]----> Thread-8,java_lang.thread_synchronized.Sub2@15dfd77
     12:40:46,046 [INFO]----> Thread-9,java_lang.thread_synchronized.Sub2@15dfd77

    从上面可以看出,

    不同线程对子类Sub1的同一对象sub1,调用testMothed,有同步效果,分别进入该方法,分别等待5秒。(红色与红色时间差)

    不同线程对子类Sub2的同一对象sub2,调用testMothed,没有同步效果,所有线程同时进入该方法并同时等待3秒(蓝色到绿色时间差),然后同时执行(绿色时间一样)。

    因此,对"关键字synchronized不能被继承",完整描述应该是:

    1、子类继承父类时,如果没有重写父类中的同步方法,子类同一对象,在不同线程并发调用该方法时,具有同步效果。

    2、子类继承父类,并且重写父类中的同步方法,但没有添加关键字synchronized,子类同一对象,在不同线程并发调用该方法时,不再具有同步效果,这种情形即是"关键字synchronized不能被继承"的转述。(貌似很多人在这一点上存在疑惑)。

  • 相关阅读:
    编写C#程序的IDE
    MacBook Pro装Win7后喇叭没有声音
    MacBook Pro装Win7后喇叭没有声音
    MacBook Pro装Win7后喇叭没有声音
    MacBook Pro装Win7后喇叭没有声音
    Linux从入门到精通系列之NFS
    Linux从入门到精通系列之NFS
    Linux从入门到精通系列之NFS
    Docker之docker设置系统的环境变量
    mq put 消息到远程队列
  • 原文地址:https://www.cnblogs.com/jianghengsh/p/11132451.html
Copyright © 2020-2023  润新知