【问题标题】:A shared counter is not incrementing as expected on concurrent server共享计数器未按预期在并发服务器上递增
【发布时间】:2011-12-14 19:13:35
【问题描述】:

我正在尝试存储任何客户端从 ServerProtocol 类请求描述的次数。

目前,每次有新客户端加入时,计数器都会从零开始递增。有任何想法吗?

计数器类:

public class Counter {

private int counter;

public synchronized int get() {
    return counter;
}

public synchronized void set(int n) {
    counter = n;
}

public synchronized void increment() {
    set(get() + 1);
}
}

来自 ServerProtocol 类的片段:

 case OPTIONS:
            if (theInput.equals("1")) {
                theOutput = "computer program description here  -- Another? Y or N";
                counter.increment();
                System.out.println(counter.get());
                state = ANOTHER;

上面的 println 方法是在一个服务器类中将计数器的当前值打印到终端中:

ServerProtocol 类:

public class ServerProtocol {

private static final int TERMS = 0;
private static final int ACCEPTTERMS = 1;
private static final int ANOTHER = 2;
private static final int OPTIONS = 3;
private int state = TERMS;

public String processInput(String theInput) {
    String theOutput = null;

    Counter counter = new Counter();

    switch (state) {
        case TERMS:
            theOutput = "Terms of reference.  Do you accept? Y or N";
            state = ACCEPTTERMS;
            break;
        case ACCEPTTERMS:
            if (theInput.equalsIgnoreCase("y")) {
                theOutput = "1. computer program 2. picture 3. e-book";
                state = OPTIONS;
            } else if (theInput.equalsIgnoreCase("n")) {
                theOutput = "Bye.";
            } else {
                theOutput = "Invalid Entry -- Terms of reference.  Do you accept? Y or N";
                state = ACCEPTTERMS;
            }
            break;
        case ANOTHER:
            if (theInput.equalsIgnoreCase("y")) {
                theOutput = "1. computer program 2. picture 3. e-book";
                state = OPTIONS;
            } else if (theInput.equalsIgnoreCase("n")) {
                theOutput = "Bye.";
            } else {
                theOutput = "Invalid Entry -- Another? Y or N";
                state = ACCEPTTERMS;
            }
            break;
        case OPTIONS:
            if (theInput.equals("1")) {
                theOutput = "computer program description here  -- Another? Y or N";
                counter.increment();
                counter.get();
                state = ANOTHER;

            } else if (theInput.equals("2")) {
                theOutput = "picture description here -- Another? Y or N";
                state = ANOTHER;

            } else if (theInput.equals("3")) {
                theOutput = "e-book description here -- Another? Y or N";
                state = ANOTHER;

            } else {
                theOutput = "Invalid Entry -- 1. computer program 2. picture 3. e-book";
                state = OPTIONS;
            }
            break;
        default:
            System.out.println("Oops");
    }

    return theOutput;
}
}

【问题讨论】:

  • 每次客户端加入时你都调用processInput吗?每次调用该方法时,您都会创建一个新计数器。
  • 除其他答案外:如果您先递增然后获取,则可能有多个线程同时递增,然后在当前获取。所有线程只会看到相同的计数器值。考虑使用 AtomicInteger 及其 incrementAndGet 方法。
  • @Megacan 是的,每次都会调用 processInput。如下所述,使变量静态似乎可以完成这项工作

标签: java concurrency atomic


【解决方案1】:

serverprotocol 方法中的计数器实例是一个局部变量。因此,每次调用方法 processInput 时,都会创建一个新的 counter 实例,其值为零。就是这个原因。

【讨论】:

    【解决方案2】:

    您是否多次调用 processInput?

    计数器不是静态的;每次初始化时(例如Counter counter = new Counter()),计数值都会重新初始化为 0。要么将其设为静态,要么确保它只被初始化一次。

    【讨论】:

      【解决方案3】:

      您没有指定ServerProtocol 的生命周期,所以我不知道它是否是在每次客户端调用服务器时创建的,例如它是 Google App Engine 中的 servlet。

      如果不是,您至少需要将Counter counter 的定义从方法移动到类。所以Counter counter 成为班级成员。

      附言。在当前代码中将counter 设为静态会起作用,但从设计的角度来看并不酷。

      【讨论】:

        【解决方案4】:

        不确定我是否明白您的要求,但如果您希望只有 1 个柜台,您可以将其设为 static。这应该确保只有 1 个副本会增加。这有帮助吗?

        编辑:您可以阅读静态变量here

        【讨论】:

          猜你喜欢
          • 2023-01-31
          • 2020-06-30
          • 2016-07-19
          • 1970-01-01
          • 2022-08-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-06-23
          相关资源
          最近更新 更多