public class CountAction extends Action {
private Integer count = 0;
@Override
public ActionForward execute(ActionMapping mapping, ActionForm form, 
HttpServletRequest request, HttpServletResponse response) 
throws Exception {
synchronized(count){
count++;
}
PrintWriter out = response.getWriter();
out.println("count=" + count);
return null;
}

}
看struts视频时,一段统计Action被调用次数的代码
我想问的是,对count++进行同步,是不是考虑多cpu的情况?
如果只有一个cpu的话,即使多线程,因为只有count++一行代码,各线程也不可能同时执行count++吧?

解决方案 »

  1.   

    你这段代码本身就有问题吧,private Integer count = 0;你定义的是类对象,根本没有办法实现统计的。应该定义为private static Integer count = 0;另外count++即使是一个cpu,也不能保证一定就是一次执行完成,因为count++对于cpu来说并不是一个指令,而且java在这里还有一个对于Integer对象和int的转换过程。
      

  2.   

    count++;有两个操作:加一和赋值,当你赋值的时候,是有可能把另外一线程刚加好的值赋过来的,那自己线程的那个加操作就被覆盖了。
      

  3.   


    不需要声明static的,因为每个Action对象在内存中只有一份,所以Action的类变量和实例变量区别就不大了,都可以实现统计。
    你所说的“count++对于cpu来说并不是一个指令”,能有办法测出两个线程同时执行count++,结果只加了1的情况么?
      

  4.   

    我不清楚struts对Action是不是都是严格单例的,如果不是,这样的统计貌似没有意义,因为不同的CountAction 对象,count不是共有的。
      

  5.   

    Our controller servlet creates only one instance of your Action class,  and uses this one instance to service all requests. 
    struts用户手册原文。
      

  6.   

    你想要测试的话,可以试下下面的代码,几乎每次执行的效果都不一样。
    public class Test extends Thread {
    private static Integer count = 0;

    public void run(){
    for(int i=0;i<1000000;i++){
    count++;
    }
    }

    public static void main(String args[]){
    Test test1 = new Test();
    Test test2 = new Test();
    test1.start();
    test2.start();
    System.out.println(count);
    }
    }
      

  7.   

    public class Test extends Thread {
    private static Integer count = 0;
    private static Object obj = new Object();

    public void run(){
    for(int i=0;i<1000000;i++){
    //synchronized(obj){
    count++;
    //}
    }
    }

    public static void main(String args[]){
    Test test1 = new Test();
    Test test2 = new Test();
    test1.start();
    test2.start();
    try {
    sleep(10000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println(count);
    }
    }
    上面这个代码测试的很明显,注释去掉和加上立马有明显的效果,而且我还发现了一个问题,synchronized(obj)如果改成synchronized(count)根本没有效果,起不到同步作用。
      

  8.   


    public class Test extends Thread {
        private static Integer count = 0;    public synchronized void run(){
            for(int i=0;i<1000000;i++){
                count++;
            }
        }
        
        public static void main(String args[]) throws InterruptedException{
            Test test1 = new Test();
            Test test2 = new Test();
            test1.start();
            test2.start();
            Thread.sleep(2000);
            System.out.println(count);
        }
    }
    我换成上面这段代码,也没起到同步的作用???为什么?
      

  9.   

    10楼写的当然不行,
    public synchronized void run(){ 
            for(int i=0;i <1000000;i++){ 
                count++; 
            } 
        } 
    相当于
    public void run(){ 
    synchronized(this){
            for(int i=0;i <1000000;i++){ 
                count++; 
            } 
    }
        } 
    实际上两个线程是不同的对象,当然不行。
      

  10.   


    哦,3Q~!
    那为什么用count去同步也不行?
      

  11.   

    public class Test extends Thread {
        private static Integer count = new Integer(0);    public synchronized void run(){
         synchronized(count){
            for(int i=0;i<1000000;i++){
                count++;
            }
         }
        }
        
        public static void main(String args[]) throws InterruptedException{
            Test test1 = new Test();
            Test test2 = new Test();
            test1.start();
            test2.start();
            Thread.sleep(2000);
            System.out.println(count);
        }
    }
    我改进了一下,这样就行了--!
      

  12.   


    个人推测,如果只是这么写,private static Integer count = 0,jvm将int自动打包Integer时候,
    并不是用同一个Integer对象。