首页 新闻 会员 周边 捐助

关于java sychronized继承问题

0
悬赏园豆:10 [已解决问题] 解决于 2014-08-07 10:55

看到网上说【synchronized关键字是不能继承的,也就是说,基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法】取自【http://www.cnblogs.com/devinzhang/archive/2011/12/14/2287675.html】。

但是我经过测试是可以继承的,请问以上网上说的是否正确?若是正确的,如何证明呢?

易之名的主页 易之名 | 初学一级 | 园豆:103
提问于:2014-08-06 22:58
< >
分享
最佳答案
0

不会继承synchronized的。

public class A extends B{
    private int a=0;
    public void add() {
        a+=1;
    }
    
    @Override
    public void run() {
        try {
            while (true) {
                add();System.out.println(a);
                Thread.sleep(1000);
                
            }
        } catch (Exception e) {
            // TODO: handle exception
        }
        
    }
    public static void main(String[] args) {
        A aobj=new A();
        
        for (int i = 0; i < 4; i++) {
            Thread thread=new Thread(aobj);
            thread.start();
        }
    }
}

class B implements Runnable{
    private int b=0;
    public synchronized void add() {
        b+=1;
    }
    public void run() {
        while(true){
            add();
            System.out.println(b);
        }
    }
}

你可以跑一下这段程序,如果输出的数字中,一直不会出现重复的(不管输出的数字顺序是否从小到大),就说明是继承了synchronized;如果会出现重复的,就说明没有继承Synchronized。

收获园豆:10
乐享程序员 | 小虾三级 |园豆:930 | 2014-08-07 06:12

我刚才把上面的程序跑了一下,结果中出现:

这就说明了,在同一时间,有两个线程同时拿到了60,然后都执行add(),两个线程都将a值加1,变为61。

乐享程序员 | 园豆:930 (小虾三级) | 2014-08-07 06:19

@螺 丝 钉: 

class A重写了class B的add()方法,这当然是不同步。我是指若不重写父类同步方法时,子类是否会继承synchronized。对于【synchronized关键字是不能继承的】这句话,我的理解是指子类在没有重写情况下,是否会继承synchronized。

易之名 | 园豆:103 (初学一级) | 2014-08-07 09:32

@易之名: 

synchronized锁是对象锁,与那个类无关,也与继承无关。锁是对象拥有的。

乐享程序员 | 园豆:930 (小虾三级) | 2014-08-07 09:35

@螺 丝 钉: 简单点说,

若class A没有重写add(),那么输出结果是否会出现重复数字?

易之名 | 园豆:103 (初学一级) | 2014-08-07 09:39

@易之名: 

不会的,如果不重写add(),那么变化的是b,而不是a(a一直是0),b是B的字段,A的对象不具备b字段,在所有线程执行add()期间,只能有一个线程改变b,b就不会重复

乐享程序员 | 园豆:930 (小虾三级) | 2014-08-07 09:50

@螺 丝 钉: 

【在所有线程执行add()期间,只能有一个线程改变b】理由是什么?

易之名 | 园豆:103 (初学一级) | 2014-08-07 09:55

@易之名: 仅仅因为b字段是class B的字段?

易之名 | 园豆:103 (初学一级) | 2014-08-07 09:56

@易之名: 同步和字段又没有什么关系。

易之名 | 园豆:103 (初学一级) | 2014-08-07 09:56

@易之名: 

只能有一个线程改变b,不是因为它是B的字段,而是因为add()有synchronized,A中没有方法add(),B中的方法add()是public,所以add()才可以被A继承可见,运行add()期间,执行的实际是隐藏的B的对象的add(),add()有synchronized修饰,因此执行隐藏的B的对象的add()方法时,只会有一个线程改变b.

 

隐藏的B对象,是在创建A的对象时创建的。

乐享程序员 | 园豆:930 (小虾三级) | 2014-08-07 10:03

@螺 丝 钉: 嗯,明白。

那现在一个问题是【synchronized关键字是不能继承的】这句话如何去理解,这里的继承指的是什么?

正如class A没有重新add()方法时,那么是否可以说class A继承了class B的synchronized add()方法?

如果是继承,那不就说明继承继承了synchronized了吗?

易之名 | 园豆:103 (初学一级) | 2014-08-07 10:13

@易之名: 好了,谢谢,我知道原因了。

易之名 | 园豆:103 (初学一级) | 2014-08-07 10:15

@易之名: 

继承了方法add()只是说A的对象能使用add(),不是说A的对象拥有方法add()。

synchronized关键字是不能继承的理解应当是,A的对象是否具备同步功能,也就是说A的对象是否拥有锁。

你上面考虑的两种情况,A的对象都没有锁,所以可以反推出不能 被继承。

乐享程序员 | 园豆:930 (小虾三级) | 2014-08-07 10:22

@螺 丝 钉: 

如果在A中重写了add(),但不使用synchronized修饰,只说明A的对象拥有了add(),但不会加锁。

在A中重写了add(),并且使用synchronized修饰,说明A的对象拥有了add(),执行add(),A的对象会加锁。

 

synchronized能够进行数据同步,保证可见性和原子性,是因为在JVM内部,是通过隐藏的加锁机制实现的。看到synchronized,就是要让对象加锁。

乐享程序员 | 园豆:930 (小虾三级) | 2014-08-07 10:26
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册