AlgoMaster Logo
AlgoMasterDesign Shared Countereasy

Design Shared Counter

easy

A counter is shared across a whole application. Two unrelated components obtain it independently, yet both must update and read one count.

Counter starts as an ordinary class. Its constructor is public and getInstance() builds a new object on every call, so two components that ask for the counter end up with two unrelated counts. Your task is to turn Counter into a thread-safe singleton and complete its methods.

CounterGate is the driver used by the judge. It asks Counter for two handles independently and delegates A-labelled and B-labelled calls through those handles. It is already complete and must not be modified.

  • Counter.getInstance() returns one controlled, thread-safe instance. Code outside the class must not be able to construct a second one.
  • int increment() adds one to the count and returns the new value.
  • int getCount() returns the current count.
  • void reset() sets the count back to 0. It changes only the value; the singleton object stays the same.
  • CounterGate() calls reset() for test isolation, then obtains handle A and handle B with two separate getInstance() calls.
  • boolean sameInstance() returns whether the two handles refer to the same Counter object.
  • int incrementA() and int readA() use handle A.
  • int incrementB() and int readB() use handle B.

This introductory exercise teaches controlled construction, stable identity, shared state, and basic synchronization.

All judge cases run in one process. reset() clears the count between cases, but it must never clear or replace the stored singleton reference.

Thread-safety requirement: The singleton must be thread-safe: both instance publication and count reads, resets, and increments must remain correct under concurrent calls.

TypeScript operations are synchronous within one JavaScript realm; separate workers have separate singleton scopes.

Example 1:

Input:

Output:

Explanation: Handle A and handle B were obtained independently but refer to the same object. An increment through A is therefore visible through B.

Example 2:

Input:

Output:

Explanation: Three increments arrive through two independently obtained handles and build one running total of 3. Both handles read that same value.

Constraints

  • At most 100 calls in total are made across all methods.
  • Judge operations are sequential, while thread safety is evaluated from the submitted design.
  • Every judge case runs in the same process, so reset() must clear the count without replacing the singleton object.

Starter Code

Turn Counter into a thread-safe singleton and complete its TODOs. CounterGate is complete driver code and must not be modified.

How the design is graded

needs 7/10 to pass
  • One thread-safe instance

    Full marks when `Counter` owns one safely published instance for the lifetime of the process and construction is controlled. Lose points heavily when construction remains public, the accessor can return different objects, or initialization uses an unsafe check-then-create sequence.

  • Synchronized shared count

    Full marks when `increment`, `getCount`, and `reset` protect the same count state so concurrent increments cannot be lost and the two driver handles observe one running value. Lose points for unsynchronized mutation or state stored outside `Counter`.

  • Stable reset semantics

    Full marks when `reset` clears only the count and never clears or replaces the singleton reference. Lose points for recreating the singleton between cases or printing to stdout.

Passing every test is not enough on its own. A submission is accepted only when the design also clears the bar.

Hints

Loading...
CallReturns
new CounterGate()null
sameInstance()true
incrementA()1
readB()1

Handle A and handle B were obtained independently but refer to the same object. An increment through A is therefore visible through B.

Run checks these cases. Submit also runs a larger hidden set.