# Can \`Arc::is\_unique\` return \`true\` in this example?

**URL:** <https://users.rust-lang.org/t/can-arc-is-unique-return-true-in-this-example/140998>\
**Category:** help\
**Created:** [June 29, 2026, 1:13pm UTC](https://users.rust-lang.org/t/can-arc-is-unique-return-true-in-this-example/140998 "2026-06-29T13:13:10Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![xmh0511](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/xmh0511/32/28198_2.png) [@xmh0511](https://users.rust-lang.org/u/xmh0511)\
**Post date:** [June 29, 2026, 1:13pm UTC](https://users.rust-lang.org/t/can-arc-is-unique-return-true-in-this-example/140998/1 "2026-06-29T13:13:11Z")

</div>

Consider this [example](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=a808711b57507bd966349938d1d680d5):

```rust
#![feature(arc_is_unique)]
use std::sync::{
    Arc,
    atomic::{AtomicBool, AtomicPtr, Ordering},
};
use std::thread;
fn main() {
    let mut is_unique = false;
    let arc = Arc::new(1); // #0
    let ptr = AtomicPtr::new(std::ptr::null_mut());
    let flag = AtomicBool::new(false);
    let ptr_rf = &ptr;
    let flag_rf = &flag;
    thread::scope(|s| {
        // thread 1
        s.spawn(move || {
            // clone() behaves like `strong.fetch_add(1,Relaxed)`
            let arc2 = arc.clone(); // #1
            ptr_rf.store(Arc::into_raw(arc2) as *mut i32, Ordering::Relaxed); // #2
            while !flag_rf.load(Ordering::Acquire) {} // #3
        });
        // thread 2
        s.spawn(|| {
            let raw_arc = loop {
                let val = ptr.load(Ordering::Relaxed) as *const i32; // #4
                if !val.is_null() {
                    break val;
                }
            };
            let arc = unsafe { Arc::from_raw(raw_arc as *const _) };
            is_unique = Arc::is_unique(&arc); // #5
            flag.store(true, Ordering::Release); // #6
        });
    });
    println!("{}", is_unique);
}

```

In this example, `#0` creates the control block and initializes `strong` and `weak` to `1`, respectively; these modifications all _happens-before_ the beginning of the two threads. The `clone()` at `#1`, as explained in the comment, is a modification that increases `strong` by one.

Since `#2` and `#4` both use `Relaxed` memory ordering, the modification at `#1` is **unordered** with `#5`; In other words, `#1` doesn't happen before `#5`, the modification at `#1` is not guaranteed to be visible to `#5`. According to the write-read coherence rule:

> If a side effect X on an atomic object M happens before a value computation B of M, then the evaluation B takes its value from X or from a side effect Y that follows X in the modification order of M.

Such a side effect `X` in this example is the modification to `strong` at `#0`; this means the load to `strong` within `Arc::is_unique` is valid to read the initial value `1`.

`#6` synchronizing with `#3` ensures that the load to `strong` within `Arc::is_unique` cannot read the modification of the drop of `Arc` in thread 1, which could be `1`. This excludes the case that `Arc::is_unqiue` returns `true` because it reads that value.

So, is `is_unique` in this example possible to be `true`?

### PS:

The implementation of `Arc::is_unique` is approximately as follows:

```rust
    pub fn is_unique(this: &Self) -> bool {
        // lock the weak pointer count if we appear to be the sole weak pointer
        // holder.
        //
        // The acquire label here ensures a happens-before relationship with any
        // writes to `strong` (in particular in `Weak::upgrade`) prior to decrements
        // of the `weak` count (via `Weak::drop`, which uses release). If the upgraded
        // weak ref was never dropped, the CAS here will fail so we do not care to synchronize.
        if this.inner().weak.compare_exchange(1, usize::MAX, Acquire, Relaxed).is_ok() {
            // This needs to be an `Acquire` to synchronize with the decrement of the `strong`
            // counter in `drop` -- the only access that happens when any but the last reference
            // is being dropped.
            let unique = this.inner().strong.load(Acquire) == 1;

            // The release write here synchronizes with a read in `downgrade`,
            // effectively preventing the above read of `strong` from happening
            // after the write.
            this.inner().weak.store(1, Release); // release the lock
            unique
        } else {
            false
        }
    }

```

---

<div class="post-metadata">

**Author:** ![nerditation](https://avatars.discourse-cdn.com/v4/letter/n/e79b87/32.png) [@nerditation](https://users.rust-lang.org/u/nerditation)\
**Post date:** [June 29, 2026, 2:30pm UTC](https://users.rust-lang.org/t/can-arc-is-unique-return-true-in-this-example/140998/2 "2026-06-29T14:30:47Z")

</div>

I believe the answer is yes, it is possible for `is_unique` to be `true` in this example.

the key insight is the two store operations in thead 1, one for the strong count, one for the atomic pointer, can be observed in different order from the perspective of a different thread, because the two memory transaction writes to **different** memory locations, and both have the `Relaxed` order.

this would probably not happen on x86 architecture, but can actually happen on weak ordered hardware, not just a theoretical possibility, I think.

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/steffahn/32/47569_2.png) [@steffahn](https://users.rust-lang.org/u/steffahn)\
**Post date:** [June 29, 2026, 7:53pm UTC](https://users.rust-lang.org/t/can-arc-is-unique-return-true-in-this-example/140998/3 "2026-06-29T19:53:59Z")

</div>

You can run this locally with

```rust
MIRIFLAGS="-Zmiri-many-seeds" cargo miri run

```

and see many runs returning `true` 😉

* * *

_Edit:_ similarly, [doing multiple iterations of this](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=a3f977576d2e6f17dcbffb9b0eb18b0d) will also show it on the playground

_(given the threads live in a scope, there is no concurrency interaction to be expected between different iterations)_

* * *

_Edit2:_ Also, of course the _underlying_ reasons why this “fails” to begin with is that the operations of `Arc` are implemented based on the assumption that any transfer of ownership of an `Arc` – or transfer of a borrow of an `Arc` (via immutble or mutable reference) – to another thread, is itself synchronized through different mechanisms.

While this code example does work around some of the _other_ issues that such a transfer of a pointer _without synchronization_ would often entail, such as the ability to access a memory location before it’s initialized, or after it’s freed (by making the initialization happen in the main thread; and by synchronizing the drop operations\[1\]).

Things that can also create problems include e.g.: mutating the `Arc`’s content while it’s still uniquely referenced by thread 1 (even just [this](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=42ddaeb1fd7a0f4552db1d82d115b573) is enough to make `miri` always reject the whole thing):

```diff
- let arc = Arc::new(1); // #0
+ let mut arc = Arc::new(1); // #0
    let ptr = AtomicPtr::new(std::ptr::null_mut());
    let flag = AtomicBool::new(false);
    let ptr_rf = &ptr;
    let flag_rf = &flag;
    thread::scope(|s| {
        // thread 1
        s.spawn(move || {
+ Arc::get_mut(&mut arc);
            // clone() behaves like `strong.fetch_add(1,Relaxed)`
            let arc2 = arc.clone(); // #1

```

* * *

1. though actually, I don’t think this particular step makes too much of a difference here – actually it seems more to only exists such that _any_ `is_unique == true` result is obviously “unsound”, never possibly just a case of “well the other thread had already dropped it”

---

<div class="post-metadata">

**Author:** ![xmh0511](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/xmh0511/32/28198_2.png) [@xmh0511](https://users.rust-lang.org/u/xmh0511)\
**Post date:** [June 30, 2026, 1:49am UTC](https://users.rust-lang.org/t/can-arc-is-unique-return-true-in-this-example/140998/4 "2026-06-30T01:49:17Z")

</div>

> MIRIFLAGS="-Zmiri-many-seeds" cargo miri run

I didn't know this approach. Can this approach be directly used on the playground?

> by synchronizing the drop operations

The purpose is only to make the load of `strong` within `Arc::is_unique` either read the modification at `#1` or the earlier modification(i.e., the initial value `1`) in the modification order of `strong`.

I think the read-only access to `arc` in thread 2 is safe because the existence of a `drop` of `arc` in thread 2 ensures that the access _happens-before_ the deallocation of the resource, regardless of the order in which the drop in the two threads happens.

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/steffahn/32/47569_2.png) [@steffahn](https://users.rust-lang.org/u/steffahn)\
**Post date:** [June 30, 2026, 2:28am UTC](https://users.rust-lang.org/t/can-arc-is-unique-return-true-in-this-example/140998/5 "2026-06-30T02:28:14Z")

</div>

> [@xmh0511](#):
>
> The purpose is only to make the load of `strong` within `Arc::is_unique` either read the modification at `#1` or the earlier modification(i.e., the initial value `1`) in the modification order of `strong`.

I realized this is likely the case while writing the sentence (see the footnote I had already added 😅)

> [@xmh0511](#):
>
> I think the read-only access to `arc` in thread 2 is safe because the existence of a `drop` of `arc` in thread 2 ensures that the access _happens-before_ the deallocation of the resource, regardless of the order in which the drop in the two threads happens.

I think you're probably correct about this.

* * *

> [@xmh0511](#):
>
> Can this approach be directly used on the playground?

I don't know of a supported _direct_ way. _Indirectly_ though - well - you could just call `miri` with [std::process::Command](https://doc.rust-lang.org/std/process/struct.Command.html) I guess…

* * *

_Edit:_ IDK why it seems to want to re-compile _some_ of the dependencies, and it seems like it wants me to hit the run button twice before actually working but otherwise… [this seems to work](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=adc1679657d4f30075ffcc7746d5930d) ^^

Edit2: Ah! Probably RAM usage limits, [`-j 1` makes it work first try](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=638f18f80e81962794d19857c55098ef)!

_[Run these with the normal “Run” button, **not** through selecting `miri` in the tools section.]_

---

<div class="post-metadata">

**Author:** ![xmh0511](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/xmh0511/32/28198_2.png) [@xmh0511](https://users.rust-lang.org/u/xmh0511)\
**Post date:** [June 30, 2026, 3:31am UTC](https://users.rust-lang.org/t/can-arc-is-unique-return-true-in-this-example/140998/6 "2026-06-30T03:31:06Z")

</div>

Thanks. I find that the result `true` is rarely reproducible in run mode; I cannot see `true` in run mode. However, this can be merely reproduced in the common miri mode.

---

<div class="post-metadata">

**Author:** ![system](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/system/32/51372_2.png) [@system](https://users.rust-lang.org/u/system)\
**Post date:** [September 28, 2026, 3:31am UTC](https://users.rust-lang.org/t/can-arc-is-unique-return-true-in-this-example/140998/7 "2026-09-28T03:31:20Z")

</div>

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.
