What changes in JMeter's Counter when Track counter independently for each user is ticked?
answer
- One element instance, two code paths
- Ask what is shared and what is copied
- The output side does not change
- One mode locks, the other uses ThreadLocal
basics
~10 sTicked, every thread counts its own private sequence from the start value. Unticked, all threads advance one shared synchronized sequence, so each iteration anywhere in the run takes the next distinct number.
solid answer
~40 s`CounterConfig` is a `NoThreadClone` element, so a single instance is shared by all threads and the checkbox chooses which path that instance takes. Unticked, it keeps one `globalCounter` field updated inside a `synchronized` block, so threads draw from one sequence and no two iterations get the same number. Ticked, it keeps the count in a `ThreadLocal`, so every thread starts at the configured start value and walks its own sequence. Both modes wrap back to the start once the maximum is passed. The part that matters for scope: **both** branches write the result into the calling thread's own variables map. A `Counter` never produces a property, so `${counterVar}` is a variable lookup either way and no other thread can change it mid-iteration. The checkbox shares the *sequence*, not the *storage*.
go deeper
Know that JMeter's Counter has a per-user checkbox and that ticking it restarts the count for each thread rather than continuing one shared sequence.
Explain both paths: a synchronized shared field when unticked, a ThreadLocal when ticked, and note that the resulting value lands in a per-thread variable either way.
Pick the mode from the data requirement rather than by habit. Say when run-wide distinct values matter, and recognise that the shared mode briefly serialises threads at each iteration.
Judge whether a shared counter is the right way to allocate test data at all, given that it couples every thread to one sequence, and decide what the team uses instead when it is not.
The `Counter` config element is the clearest small illustration of this leaf's distinction, because it lets you choose whether its *state* is shared while giving you no choice at all about where its *output* goes. ## What the checkbox switches `CounterConfig` is marked `NoThreadClone`, so unlike most elements there is one instance shared by every thread rather than a copy per thread. The `Track counter independently for each user` checkbox then picks which of two code paths that shared instance takes at the start of each iteration: - **Unchecked** — the element keeps a single `globalCounter` field and updates it inside a `synchronized` block. Each iteration by any thread takes the next number and advances the count, so the sequence is shared: with three threads the values handed out are 1, 2, 3, 4 and so on across all of them, and no two iterations receive the same number. - **Checked** — the element keeps the count in a `ThreadLocal`. Every thread starts from the configured start value and advances its own private sequence, so all three threads see 1, then all three see 2. When the count passes the configured maximum it wraps back to the start value in both modes. ## Where the result always goes This is the part worth remembering. Both branches finish the same way — the number is written into the calling thread's own variables map under the configured variable name. There is no mode in which a `Counter` writes a property. | | Counter state | Value delivered as | |---|---|---| | Unchecked | one shared, synchronized sequence | a per-thread variable | | Checked | one `ThreadLocal` sequence per thread | a per-thread variable | So `${counterVar}` is a variable lookup in both cases, and it is safe to read at any point in the iteration without another thread changing it underneath you. The sharing that the checkbox controls is the *sequence*, not the *storage*. ## Choosing between the modes - Leave it **unchecked** when the numbers must be distinct across the whole run — allocating a distinct account or record identifier to each iteration, for example, so that no two iterations collide on the same data. - Tick it when each simulated user should walk the same range independently, so every thread covers the same values. The unchecked mode's `synchronized` block is worth a moment's thought, since it briefly serialises every thread that reaches the element on each iteration. That is a mechanical consequence of a shared sequence rather than a reason to avoid the element, but it is why the per-user mode uses a `ThreadLocal` instead of a lock.
- Does an unticked Counter store its value in a property, since the count is shared?No. The shared part is the internal sequence; the number produced is still written into the calling thread's own variables map. A Counter never writes a property, so the value is read back with a plain ${varName} in both modes.
- Which mode would you choose to give every iteration a distinct account identifier?The unticked, shared mode. It advances one synchronized sequence across all threads, so no two iterations anywhere in the run receive the same number. The per-user mode restarts each thread at the start value, which would hand the same identifier to several threads.
saying these in an interview costs you the question
- Thinks an unticked Counter writes its value to a property
- Expects the per-user mode to still produce run-wide unique numbers
- Assumes each thread gets its own copy of the Counter element
- Believes another thread can change ${counterVar} mid-iteration
- Says the counter stops rather than wraps at its maximum