看到网上说【synchronized关键字是不能继承的,也就是说,基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法】取自【http://www.cnblogs.com/devinzhang/archive/2011/12/14/2287675.html】。
但是我经过测试是可以继承的,请问以上网上说的是否正确?若是正确的,如何证明呢?
不会继承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。
我刚才把上面的程序跑了一下,结果中出现:
这就说明了,在同一时间,有两个线程同时拿到了60,然后都执行add(),两个线程都将a值加1,变为61。
@螺 丝 钉:
class A重写了class B的add()方法,这当然是不同步。我是指若不重写父类同步方法时,子类是否会继承synchronized。对于【synchronized关键字是不能继承的】这句话,我的理解是指子类在没有重写情况下,是否会继承synchronized。
@易之名:
synchronized锁是对象锁,与那个类无关,也与继承无关。锁是对象拥有的。
@螺 丝 钉: 简单点说,
若class A没有重写add(),那么输出结果是否会出现重复数字?
@易之名:
不会的,如果不重写add(),那么变化的是b,而不是a(a一直是0),b是B的字段,A的对象不具备b字段,在所有线程执行add()期间,只能有一个线程改变b,b就不会重复
@螺 丝 钉:
【在所有线程执行add()期间,只能有一个线程改变b】理由是什么?
@易之名: 仅仅因为b字段是class B的字段?
@易之名: 同步和字段又没有什么关系。
@易之名:
只能有一个线程改变b,不是因为它是B的字段,而是因为add()有synchronized,A中没有方法add(),B中的方法add()是public,所以add()才可以被A继承可见,运行add()期间,执行的实际是隐藏的B的对象的add(),add()有synchronized修饰,因此执行隐藏的B的对象的add()方法时,只会有一个线程改变b.
隐藏的B对象,是在创建A的对象时创建的。
@螺 丝 钉: 嗯,明白。
那现在一个问题是【synchronized关键字是不能继承的】这句话如何去理解,这里的继承指的是什么?
正如class A没有重新add()方法时,那么是否可以说class A继承了class B的synchronized add()方法?
如果是继承,那不就说明继承继承了synchronized了吗?
@易之名: 好了,谢谢,我知道原因了。
@易之名:
继承了方法add()只是说A的对象能使用add(),不是说A的对象拥有方法add()。
synchronized关键字是不能继承的理解应当是,A的对象是否具备同步功能,也就是说A的对象是否拥有锁。
你上面考虑的两种情况,A的对象都没有锁,所以可以反推出不能 被继承。
@螺 丝 钉:
如果在A中重写了add(),但不使用synchronized修饰,只说明A的对象拥有了add(),但不会加锁。
在A中重写了add(),并且使用synchronized修饰,说明A的对象拥有了add(),执行add(),A的对象会加锁。
synchronized能够进行数据同步,保证可见性和原子性,是因为在JVM内部,是通过隐藏的加锁机制实现的。看到synchronized,就是要让对象加锁。