Can we somehow reinitialize thread local variable after every 10 threads

Hi,

I have a thread local variables. I want something like this:

static mut i:usize = 1;

thread_local! {
    static HASHMAP_DOMCAT:   RefCell<HashMap<String,PolicyRec,fasthash::RandomState<xx::Hash64>>> = {
        let map_domcat = create_domcat_hashmap(true);
        RefCell::new(map_domcat)

// i want to do something like below:
**if tid==(i*10){**
**let map_domcat = create_domcat_hashmap(false);**
**        RefCell::new(map_domcat)**
i++
**}**

    };
}

can it be done someway?

I don't see why it can't be done.

If you want the value to change itself "magically" every 10 seconds, then you will need to modify that value from a different thread, which poses a difficulty: you need to share the variable with another thread, and synchronize the access. You'll need to use Arc<Mutex<T>> instead of RefCell, and spawn another thread that does something like loop { sleep(10sec); change_the_variable(); }.

If you change from the same thread, it's a matter of calling borrow_mut() on the refcell and assigning a new value.

1 Like

when i try it, the new hashmap only gets reflected in 10th thread then remaining(meaning next 9 threads) again get the old ones.

don't want to use arc mutex or any locks as its slowing down the process when 40+ threads come.

Have you seen what @kornel has said?

I wanted to update the global variable itself for every next 10 threads inside thread local.
Not trying to update from some specific thread.

I see. Just the counter used when creating a thread?

Don't use static mut, at all. It's broken and unsafe. Forget it exists.

You must make the counter AtomicUsize.

ok. but this doesn't do the work. as i only see the new map reflected in every 10th thread, not for next all 10 threads.

If you make it atomic with SeqCst ordering, it will instantly change from perspective of all threads. If you use fetch_add on it, it will reliably increase the counter (read-modify-write will not).

Ok. Not sure if i got it right.
So you mean just the increment of the counter will work, reinitializing of the map won't?

I'm confused about what you want to achieve. For the counter, Atomic is the right type. For the hashmap, it depends what you want to do, it may need to be Arc<Mutex>> as I've mentioned previously, but I do not understand your question.

Ok.

I'm initializing a hashmap using thread local, which is separate for each thread right.
So first 10 threads can take up this.

Then I want to update or reinitialize this thread local variable(hashmap) for next 10 threads. i think this should not create race condition because its just updating the local variable to each thread, and which will be applicable for upcoming threads right?

The question is, what do you want to reinitialize? Newly created threads already can't know what other threads have done with their thread-locals, they'll get the fresh hashmap each. What is the expected semantics? It'd be better if you say what you're trying to do, not how you're trying to get there.

ok, At First, Thank you all for your time.

So i am creating a hashmap which needs to be updated after every next 10 threads(these threads are doing lookup from the hashmap).
for exa: thread 1 to 10 have 2 entries in hashmap.
thread 11 - 20 gets updated hashmap which 4 entries in hashmap(suppose 3 new entries added and 2 removed)
.... and so on.
I am using refcell with thread local to initialize the map. but if i update the hashmap in main thread, it won't reflect in other threads which spawns from main threads.
I don't want to use locks or arc mutex. so trying to find a workaround for getting updated hashmap accessible to newer threads(in my case i'm considering after every 10 threads, next 10 threads should get updated map)

So I was thinking after every 10 threads run, I call a function to get the updated data from file and reinitialize or update the thread local hashmaps.

This already means that something here must be static, not thread-local, since thread-local is, well, local for each thread.

...and what would the first ten threads see, after the thread 11 was created? Will they see the same 2 entries they've already seen, or the same 4 entries as the thread 11 does? This will give two different possible solutions.

If you need threads to communicate, you have to synchronize them, one way or another. It can be Mutex, it can be RWLock, it might be something channel-based, but some kind of synchronization must be - or your code would be open for data races.

2 Likes

...and what would the first ten threads see, after the thread 11 was created? Will they see the same 2 entries they've already seen, or the same 4 entries as the thread 11 does? This will give two different possible solutions.

while doing if 10 threads can see the same 2 entries that is also ok. and if it starts seeing 4 entries then also its ok. this is not concern actually. because either it should be updated or the same for those first 10 threads.

If you need threads to communicate, you have to synchronize them, one way or another. It can be Mutex, it can beRWLock , it might be something channel-based, but some kind of synchronization must be - or your code would be open for data races.

Thats why i was looking a way to update the local variable(thread local ones), so race condition can be avoided. or probably we can put sleep for 2sec or something while update happens.

The update in thread local variable at once, won't work for the upcoming thread?
Like if i update or reinitialize the thread local variable after 10 threads(suppose by putting sleep), the next threads won't see that new/updated map?

Thread-local variable can be accessed only from the thread it is created on, by definition.

The next threads will see their own thread-local variables, which are created freshly and doesn't know at all about their counterparts in other threads.

Each thread-local variable is initialized exactly once, when the thread first accesses it. No other thread can access it in any way— that variable name instead refers to their version of the thread-local variable.

If I understand correctly, what you actually want is a global variable which contains the most up-to-date map, and you want each thread to maintain a local, slightly-out-of-date, copy that can be accessed without synchronization:

use once_cell::sync::Lazy;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};

static GLOBAL_MAP: Lazy<Mutex<Arc<HashMap<String, String>>>> = Lazy::new(|| Default::default());

thread_local! {
    static LOCAL_MAP: Arc<HashMap<String,String>> = Arc::clone(&GLOBAL_MAP.lock().unwrap());
}

Each thread, when it first tries to access LOCAL_MAP, will make a copy of the then-current GLOBAL_MAP. Any changes to GLOBAL_MAP will only be reflected in the LOCAL_MAP of future threads.

2 Likes