书上说这个doesn't make sense,我实在想不通,希望各位大大帮一下
比如:public class Counter { private static int c = 0;

private int id;

public Counter() {
id = c;
c++;
} public int getId() {
return id;
}
}会不会有这种情况:A线程都调new Counter(),然后到id = c;完成后B取调new Counter();最后得到相同的id
小弟一时绕不过来,大家帮帮吧,尽量说清楚些

解决方案 »

  1.   


    public class Counter {    private static int c = 0;
        
        private int id;
        
        public Counter() {
        
         synchronized (this) {//这样吧
         id = c;
                    c++;
    }
            
        }    public int getId() {
            return id;
        }
    }
      

  2.   

    哪本书上说的,没有synchronized肯定不能用于多线程。
    你在id = c;c++;之间调用Thread.sleep(long time);或者
    用eclipse的debug很容易看到c的值有冲突。
    把书上的原话贴出来看一下。
      

  3.   

    另外,不是synchronized (this) {
                id = c;
                    c++;
            }
    而是synchronized (Counter.class) {
                id = c;
                    c++;
            }
    c是静态变量,属于整个类,锁住实例对象this也没用。
      

  4.   

    答:
    1)构造器是不能用synchronized来修饰的(一句话:不能用abstract,final,static,synchronized及native来修饰只能是public ,protected,private)
    2)JVM只能保证类的初始化过程是synchronized的.对象的初始化当然不是synchronized的
    3)由于int c是static 型的,因此必须要(正如:3楼所说):
    synchronized (Counter.class) { 
                id = c; 
                    c++; 
            } 
      

  5.   


    public class Test 

    public static int id=0;
    private int c;
    public Test(){
    c=id;
    System.out.println("一个线程到达");
    try{
    //睡眠
    Thread.currentThread().sleep(1000*10);
    }catch(InterruptedException e){
    e.printStackTrace();
    }
    id++;
    }
    public int getC(){
    return c;
    }
    public static void main(String [] args){
    TestThread t1=new TestThread();
    TestThread  t2=new TestThread();
    t1.start();
    t2.start();
    }

    class  TestThread extends Thread{
    public void run(){
    Test test=new Test();
    System.out.println(test.getC());
    }
    }确实如此,两个对象得到c一样,改为如下:public class Test 

    public static int id=0;
    private int c;
    public Test(){
    synchronized(Test.class){
    c=id;
    System.out.println("一个线程到达");
    try{
    //睡眠
    Thread.currentThread().sleep(1000*10);
    }catch(InterruptedException e){
    e.printStackTrace();
    }
    id++;
    }
    }
    public int getC(){
    return c;
    }
    public static void main(String [] args){
    TestThread t1=new TestThread();
    TestThread  t2=new TestThread();
    t1.start();
    t2.start();
    }

    class  TestThread extends Thread{
    public void run(){
    Test test=new Test();
    System.out.println(test.getC());
    }
    }这样没有问题
      

  6.   

    first:
    out:
    一个线程到达
    一个线程到达
    0
    0
    **************************
    second:
    out:
    一个线程到达
    一个线程到达
    0
    1
      

  7.   

    看来我的表达很有问题,我主要是想知道Constructor为什么不能用synchronized修饰(然而大部分朋友都针对
    我给的那个例子作解释,尤其是static),当然把Constructor声明成synchronized是语法错误,可以认为是规
    定的,但The Java Programming Language在说Constructors, in fact, cannot be declared synchronized.之
    前有这么一句:The constructor does not need to be synchronized because it is executed only when creating an object, and that can happen in only one thread for any given new object.并且Tutorial
    上也有说:Synchronizing constructors doesn't make sense, because only the thread that creates an object should have access to it while it is being constructed. 小弟不是很能理解:难道JVM保证了一
    个在调一个类的Constructor的时候其他线程,其他线程不能在这个时刻也调这个类的Constructor?
      

  8.   

    synchronized关键字使用的当前对象作为锁的
    你在构造方法上使用synchronized这时对象还未产生
    如何能使用?
      

  9.   

    synchronized修饰整个方法,相当于把整个方法体括在synchronized(this) { }中,而要执行到这个方法的前提是拿到this——即当前对象的锁;而构造函数执行完毕之前,this还未返回给任何调用者,所以给构造函数加synchronized,就等于说this对象还未产生,就试图去拿到它的锁,当然没有意义了。
      

  10.   

    答:不是这样理解的.它是讲:线程A在执行new Counter()时,线程B当然可以并发执行自己的new COunter();.这两个Counter()初始化的对象是不同的.
      

  11.   


    就是这个意思了,不是同一个对象的同步都没有意义的,构造函数同步自然就没有意义了,
    “书上说这个doesn't make sense
      

  12.   

    即:线程A与线程B并发执行的代码是相同的(都是COunter();),初始化的对象(this)是不同的.因此:是从这一个含义来说明(或规定)构造器不能用synchronized修饰.
      

  13.   


    There is no practical need for a constructor to be synchronized, because it would lock the object under construction, which is normally not made available to other threads until all constructors for the object have completed their work. 没有实际的需要把构造器定义成同步的,因为它将会在构造的时候锁住该对象,直到所有的构造器完成它们的工作,这个构造的过程对其它线程来说,通常是不可访问的。
    所以,对于成员变量的访问不可能出现同步问题。  但对于静态变量的访问需要自己显示的同步操作。
      

  14.   

    这里的没有意义,does not make sense 说的是什么?
    说的是
    在你new 一个counter一个对象的时候,你创建的对象正在创建中,在这个时间点上边,还没有其他线程可以
    用到这个对象(你正在创建的对象)。ok,你的对象还没有生成呢?
      

  15.   

    this不是已经有了吗?又不是constructor执行完才有的
    简单来说:Constructor不能声明为synchronized是不是在多线程环境下,不用synchronized修饰Constructor
    是不会出现数据不一致的问题的,就是我给的那个例子中id永远都不会出现重复的情况(或类似的),是这样吗?开始晕了!!!
      

  16.   

    对象A和对象B,他们有自己的一套资源, 他们之间不需要同步
    constructor是用来创建对象的,对象之间没有同步的意义
    所以,构造函数就没有同步的意义,
      

  17.   

    答:几点说明:
    1)只要是在构造器内部,随时都可以进行synchronized(this){...}因此:构造器还没有初始化完成,this对象还未产生,就试图去拿到它的锁,当然没有意义了。这是不对的.
    2)18楼的shuidao兄弟引用的是"JLS 8.8.3节中的一段话",但是理解不对了.他隐含理解成:整个构造器是一个synchronizd,因而:"对于成员变量的访问不可能出现同步问题" 这也是不正确的.因为:见下例代码:
    public Counter()
    {
     new MyThread(this).start();//线程MyThrad的run将反复多次读写数据成员id
    //同时说明:这个this已经可以用了,并不是所谓的:
    //创建的对象正在创建中,在这个时间点上边,还没有其他线程可以 
    //用到这个对象(你正在创建的对象) ..(构造器中其它代码)..  //构造器中的其它代码,也是将反复多次读写数据成员id
    }
    正是多个线程同时读写同一个数据成员id!这当然可能存在同步问题.
    因此:在这种情形下,还是需要进行synchronized(this){...}.总结:构造器不能加synchronized,是一项程序语言设计上的选择(见:JLS 8.8.3 Constructor Modifiers).正常情况下,是不需要加上synchronized,但不代表所有的情况都不要加上:synchronized,更不能认为一个构造器隐含的就是一个synchronized.
      

  18.   

    在自己内部出现了新的线程,没有办法,呵呵!
    但是这个this却是可以使用了。这个时候该对象已经存在。
      

  19.   

    25楼说的很有道理。
    我想补充几点:
    1. 在构造函数一开始,this就是可用的了。
    2. 构造函数和普通函数一样,并不是默认被synchronized 的,有可能出现同步问题。
    3. 如果构造函数中访问静态变量的话,必须同步这个静态变量,否则一定会出问题。
    4. 如果只访问成员变量的话,无论在任何线程中,每一次构造函数被调用,其中的成员变量都是新建造出来的,因此不可能出现说在这个线程中运行的构造函数 会访问到另一个线程中运行的构造函数中的成员变量的情况,因此这就是我所说的“访问成员变量不可能出现同步问题”的意思。  这里的前提是,两个线程中都运行的是构造函数,而不是其他方法(例如start所启动的run方法。)。4.如果在构造函数中,把this交给其他的线程去访问,则其他线程可能在this实例还未初始化完毕时就访问了其中的变量,这有可能产生同步问题。这时需要显式同步this对象。