当前位置:编程学习 > JAVA >>

synchronized关键字不能被继承的问题

我发现许多地方提及synchronized的关键字不能被继承,但是通过实验发现synchronized的关键字是能够被继承的,是我的实验方式不对?请高手指教,谢谢

import java.text.SimpleDateFormat;
import java.util.Date;

public class TestMain {

/**
 * @param args
 */
public static void main(String[] args) {
// TODO Auto-generated method stub
        UtilChild util = new UtilChild();
        
AThread aThread1 = new AThread(util,1);
aThread1.start();
AThread aThread2 = new AThread(util,2);
aThread2.start();
AThread aThread3 = new AThread(util,3);
aThread3.start();
AThread aThread4 = new AThread(util,4);
aThread4.start();
AThread aThread5 = new AThread(util,5);
aThread5.start();
        
}

}

class Util{

public static synchronized void test1(int i){
System.out.println(getDetailDate() + " test1(i), i: " + i);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(getDetailDate() + " test1(i), i: " + i);
}

public static synchronized void test2(int i){
System.out.println(getDetailDate() + " test2(i), i: " + i);
}

public static void test3(int i){
System.out.println(getDetailDate() + " test3(i), i: " + i);
}

public synchronized void test4(int i){
System.out.println(getDetailDate() + " test4(i), i: " + i);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(getDetailDate() + " test4(i), i: " + i);
}

public synchronized void test5(int i){
System.out.println(getDetailDate() + " test5(i), i: " + i);
}

public static String getDetailDate() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(new Date());
    }
}

class UtilChild extends Util{

}

class AThread extends Thread{
UtilChild util = null;
int i = 1;
public AThread(UtilChild util, int i){
this.util = util;
this.i = i;
}

public void run(){
if(this.i== 1){
util.test1(1);
}else if(this.i== 2){
util.test2(2);
}else if(this.i== 3){
util.test3(i);
}else if(this.i== 4){
util.test4(i);
}else if(this.i== 5){
util.test5(i);
}

}
}

运行结果:


2012-03-30 00:40:02 test4(i), i: 4
2012-03-30 00:40:02 test3(i), i: 3
2012-03-30 00:40:02 test1(i), i: 1
2012-03-30 00:40:07 test4(i), i: 4
2012-03-30 00:40:07 test5(i), i: 5
2012-03-30 00:40:07 test1(i), i: 1
2012-03-30 00:40:07 test2(i), i: 2
--------------------编程问答-------------------- 路过。。。从学java开始线程就没懂过。。。 --------------------编程问答-------------------- --------------------编程问答-------------------- 这程序说明啥问题啊?test1和test4至少要隔5000ms才执行一次,test2,3,5,得到系统资源就可以执行 --------------------编程问答-------------------- 真没看出来楼主你这哪里继承synchronized的关键字,只看出多态。 --------------------编程问答-------------------- synchronized不能继承的。 --------------------编程问答-------------------- synchronized本来就不能继承…… --------------------编程问答--------------------
引用 3 楼  的回复:
这程序说明啥问题啊?test1和test4至少要隔5000ms才执行一次,test2,3,5,得到系统资源就可以执行


这个程序是多线程执行
2012-03-30 00:40:02 test4(i), i: 4
2012-03-30 00:40:02 test3(i), i: 3
2012-03-30 00:40:02 test1(i), i: 1
2012-03-30 00:40:07 test4(i), i: 4
2012-03-30 00:40:07 test5(i), i: 5
2012-03-30 00:40:07 test1(i), i: 1
2012-03-30 00:40:07 test2(i), i: 2
加睡眠只是为了防止程序执行的太快,看不出效果。
test4和test5之间同步锁是UtilChild这个类的对象,是没有互斥关系的,如果synchronized是不被继承的话,那么test4和test5的方法在UtilChild类中是不是应该理解为:
public void test4(int i){
.....
}
public void test5(int i){
.....
}
没有synchronized修饰符的?
那么一个线程执行了test4后,另外一个线程应该可以立刻执行test5,不需要等待test4方法完全执行完之后再执行test5。
同理test1和test2之间同步锁对象是UtilChild这个类本身,为什么要等test1完全执行完之后才执行test2? --------------------编程问答-------------------- 输出结果有什么问题吗?两个4之间有1出现 两个1之间也有4和5出现 说明test1和test4 test5未发生互斥 也就说明synchronized未被继承
你所说的Test4和Test5要锁同一对象怎么会没有互斥关系
多线程的过程不是按顺序往下走 它们并行在准备区里等CPU抽空来处理
执行完4后是否立即执行5是CPU说了算 不是你说了算 也不是synchronized说了算 还有你看到5在4后边执行 为什么看不到在4的执行期间还执行了3和1?
synchronized能保证的是加synchronized的所有方法在调用同一对象时只有一个方法在对其进行操作 --------------------编程问答-------------------- 不能忍啊!!!!!!!!!!看不下去了!!!!!!!!!!!!!!!
楼上居然没一个人懂楼主的问题!
深刻同情楼主! --------------------编程问答-------------------- 首先,synchronized不被继承,所以你不加这个关键字 输出结果应该也是一样的。
那么一个线程执行了test4后,另外一个线程应该可以立刻执行test5,
这是对的,没有同步另外一个线程是可以立即执行test5的,
但是由于楼主你程序的输出结果这个速度很快 cpu处理非常快 所以你没有同步 它一瞬间就把结果输出
2012-03-30 00:40:07 test4(i), i: 4
2012-03-30 00:40:07 test5(i), i: 5
这样的输出结果说明 
线程执行4.。。。在运行。。。啪。。 一下输出结果了。。。继续运行后面代码
线程执行5。。。。也在运行。。。啪。。一下也出结果了
没同步的话其实是一起运行的 只是输出结果造成你的困扰吧。 --------------------编程问答-------------------- 其实真相是这样的,“synchronized不能被继承”,这句话有2种不同意思,一种是比较正常的、很容易让人想到的意思;另一种是“不正常的”或者说是“java中文界”广泛认同了的意思。
楼主是第一种意思,其他人是第二种意思。所以,会出现该贴的尴尬讨论。
第一种理解方式:父类中有个synchronized方法,子类继承了父类,但子类没覆写该方法。通过子类实例来使用该方法时,按“synchronized不能被继承”,意思就为:该子类的该方法就变成了非synchronized方法。
第二种理解方式:synchronized并不属于方法定义的一部分,不能被继承。子类覆写了该方法,如果在覆写时不明确写上synchronized,那这个方法就不是synchronized。换句话说,虽然继承了,但是没把synchronized继承下来,也就意味着“synchronized不能被继承”。

我觉得“synchronized不能被继承”这句话,没把意思表述清楚。产生这种情况的原因,我推测是这样的:某前辈详细解释了以上2种意思,最后总结的时候,使用了“synchronized不能被继承”这句不太合适的话。某无知后辈转述前辈意思的时候,就直接用了“synchronized不能被继承”。结果一传十,十传百,这句话就传开了,也让初学者产生了迷惑。

在英文世界里,没有“synchronized不能被继承”的讨论。这也说明了点问题。

其实楼主的问题,可以记住这么句话:synchronized方法,一定要显示标明,它是不能隐式标明的。

中文里“一句话多种意思”的问题,真的是给学术界增加了不少麻烦! --------------------编程问答--------------------
引用 10 楼 beyondziming 的回复:
首先,synchronized不被继承,所以你不加这个关键字 输出结果应该也是一样的。
那么一个线程执行了test4后,另外一个线程应该可以立刻执行test5,
这是对的,没有同步另外一个线程是可以立即执行test5的,
但是由于楼主你程序的输出结果这个速度很快 cpu处理非常快 所以你没有同步 它一瞬间就把结果输出
2012-03-30 00:40:07 tes……


Shame for you!! --------------------编程问答-------------------- 刚刚我没运行 运行后发现结果继承同步方法了。 我跟楼主一样的方法了 汗。 --------------------编程问答-------------------- 以此贴为依托!!发一个倡导!
本人混迹CSDN有几年了,只看帖不回帖,shame for me!但是发现CSDN中水问题的人太多了!!
一是不理解楼主问题,二是自己也一知半解,就跑出来回答别人问题!这不误导别人么。
CSDN中真大神有很多,可是太潜水了,只看帖、只嘲笑!不回帖呀!!!应该是不屑、怕回答错、或者不愿花时间。只要认真回答问题了,即使回答错了,没人会嘲笑的!!!
CSDN的一直在走下坡路啊,看看当年的前辈是如何帮人解惑的,后辈们羞愧否!!!!

呼唤CSDN真大神出现!别再潜水了!!! --------------------编程问答--------------------
引用 11 楼 smallsmallc 的回复:
其实真相是这样的,“synchronized不能被继承”,这句话有2种不同意思,一种是比较正常的、很容易让人想到的意思;另一种是“不正常的”或者说是“java中文界”广泛认同了的意思。
楼主是第一种意思,其他人是第二种意思。所以,会出现该贴的尴尬讨论。
第一种理解方式:父类中有个synchronized方法,子类继承了父类,但子类没覆写该方法。通过子类实例来使用该方法……

没说明白,再补充下下:子类不覆写该方法时,通过子类实例调用该方法,其实使用的还是父类的方法,因此该方法仍然是synchronized。所以楼主的输出,当然是synchronized的效果。 --------------------编程问答--------------------
引用 13 楼 beyondziming 的回复:
刚刚我没运行 运行后发现结果继承同步方法了。 我跟楼主一样的方法了 汗。

“结果继承同步方法了”,同志,别这样,这句话和“synchronized不能被继承”一样,会产生歧义,误导别人的! --------------------编程问答-------------------- 子类和父类... --------------------编程问答-------------------- 子类和父类属于两个类,如果子类重写了父类,方法表指向的是子类的,如果没有重写,方法表指向的是父类的。
补充:Java ,  Java SE
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,