In JMeter, how do you make a value captured by one thread readable by all threads?
answer
- Only one store is visible to everyone
- You need a function, not a bare reference
- Publish before the readers start
- It broadcasts to all, not to one
basics
~10 sWrite it into the property map with ${__setProperty(name,value)} and read it anywhere with ${__P(name)}. Variables cannot cross threads, because every thread holds its own private copy.
solid answer
~50 s`${__setProperty(name,value)}` calls `JMeterUtils.setProperty`, writing into the single JVM-wide property map that `${__P(name)}` reads. The property map is the store a plan publishes through; variables are per-thread copies and cannot be shared at all. By default the function returns an **empty string** so it can sit in a field without altering the request; passing `true` as a third argument makes it return the **previous** value instead. The important caveat is that this is a broadcast, not a channel. Threads run concurrently, so a reader may evaluate `${__P(name)}` before the writer has run, and a second writer simply overwrites the first. The safe shape publishes a genuinely run-wide value from a part of the plan that finishes before any reader starts, such as a **setUp Thread Group**. Never use it for per-user state such as a session token.
code
text · 6 lines# In a setUp Thread Group, after the token has been extracted:
${__setProperty(auth.token,${sessionToken})} -> "" (writes, returns nothing)
${__setProperty(auth.token,${sessionToken},true)} -> the previous value
# In any later Thread Group, on any thread:
${__P(auth.token,NOT_SET)} -> the shared valuego deeper
Know that a variable belongs to one thread and cannot be handed to another, and that publishing a value to the whole run needs the property map rather than a variable.
Name the mechanism precisely: ${__setProperty(name,value)} writes into the JVM-wide map that ${__P(name)} reads, and returns an empty string unless a third argument asks for the previous value.
Talk about the race and how you removed it. Threads are concurrent, so publish from somewhere that finishes before the readers start, such as a setUp Thread Group, rather than hoping the write lands first.
Draw the line for the team between a run-wide handle, which may be published once, and per-user state, which never may. The second case is the one that produces green runs with wrong results.
Variables cannot carry a value between threads, because there is no shared variable to carry it in — each thread owns a private copy. The store every thread can both read and write is the property map, and `__setProperty` is the function a plan writes to it with. ## The mechanism `${__setProperty(name,value)}` calls `JMeterUtils.setProperty`, which writes straight into the single static property map that `${__P(name)}` reads. Because that map is JVM-wide, a value written by one thread becomes visible to every other thread in the run, in every Thread Group, for as long as the JVM lives. The function has a third argument that is easy to miss: - `${__setProperty(name,value)}` writes the value and returns an **empty string**, so it can be dropped into a field without polluting the request. - `${__setProperty(name,value,true)}` writes the value and returns the **previous** one instead. The default of returning nothing is deliberate: the call is used for its side effect, and a function that returned the value would insert it wherever the expression appears. ## What this does and does not give you It gives you a broadcast. It does not give you a channel, a queue, or any delivery guarantee. Concretely, in JMeter 6.0.0: - **There is no ordering between threads.** All threads in a Thread Group are started to run concurrently, so a thread evaluating `${__P(auth.token)}` may reach that expression before the thread whose `__setProperty` was supposed to fill it. The reader then gets whatever the built-in default supplies. - **One key holds one value.** A second writer replaces the first, so if every thread writes its own token to the same key, readers get whichever token was written most recently rather than their own. - **Nothing signals that a write happened.** A reader cannot distinguish "not yet written" from "written and empty" except by the default it gets back. - **The value outlives the thread.** It stays in the map for the rest of the run, which is usually what you want for a shared handle and never what you want for per-user state. ## When it is the right tool The honest use is a value that is genuinely singular for the run and only discoverable while it is running: a service token, an environment identifier, a generated run label. One part of the plan acquires it and publishes it with `${__setProperty(...)}`, and everything else reads it with `${__P(name,default)}`. The race disappears if the write is guaranteed to have finished before any reader exists, which in JMeter is what a **setUp Thread Group** is for. Which element runs before which is a sequencing question owned by `dev-jmeter-plan-exec-order`; what matters here is only that the published value lands in the one JVM-wide store and stays there for every later reader. ## When it is the wrong tool The anti-pattern is the one this leaf exists to name: taking a per-user value such as a session token and publishing it into a property so that a later Thread Group can use it. Every logging-in thread overwrites the same key, so the readers all present the same identity, the plan still reports green, and the defect only shows as odd behaviour on the system under test. Keep per-user state in a variable and let each thread carry its own. ## A note on scope beyond one JVM Everything above is about one JMeter process. Properties are JVM-wide, not run-wide across machines, so a `__setProperty` on one engine does not appear on another. How property values are delivered to remote engines in a distributed run is a separate subject, owned by `dev-jmeter-distributed-controller-servers`.
- Why does ${__setProperty(name,value)} return an empty string by default?Because it is called for its side effect and usually sits inside a field or a sampler name. Returning the value would insert it at the point of the call, so the default keeps the write invisible. Pass true as a third argument when you do want the previous value back.
- What goes wrong if every thread publishes its own session token to the same property?The key holds one value, so each login overwrites the last and every reader gets whichever token was written most recently rather than its own. The run still reports success, because the requests are well-formed; only the system under test sees the wrong identity.
- How do you avoid a reader running before the writer has published?Do not rely on timing between concurrent threads at all. Publish the value from a part of the plan that is guaranteed to finish first, such as a setUp Thread Group, so that no reader exists until the write has already landed in the property map.
saying these in an interview costs you the question
- Tries to share a value by setting a variable in another thread
- Publishes a per-user session token into a shared property
- Assumes the writing thread always runs before the reading thread
- Expects a property write to reach other JMeter engines automatically
- Thinks ${__setProperty(...)} inserts the value where it is called