How to handle shared resource

I'm interested what's recommend to handle my situation.

I have two wrapper methods around an API, call them 'get' and 'set', current my I have them in a separate .rs file with init_api called via lazy_static and state shared by both methods.

What's the recommend way to handle the situation?
maybe somewhere having a ctor but share the state anyway?
Not feelong good to have the global variable

The methods maybe accessed from different threads.

The general approach is to have an Arc to share data between threads. It can point to a "global" data structure. When you start a thread, you move a cloned copy of the Arc into the closure, so the thread has access to the "global" data structure.

The "global" data structure can be mutable, by using Mutex or RwLock to allow mutation.

[ I am putting "global" in quotation marks, as the data isn't really global, but still, it is shared between a given set of threads, and you can think of it that way. ]

1 Like

Here's a tiny example of what @geebee22 described. Note however, that this is certainly not a good usecase for locking with Mutexes and would better be done with par_iter from the rayon crate.

use std::sync::Arc;
use std::sync::Mutex;
use std::thread;

fn main() {
    let a = Arc::new(Mutex::new(Vec::new()));

    let mut threads = Vec::new();
    for i in 0u8..20 {
        let b = Arc::clone(&a);
        let t = thread::spawn(move || {
            let n = fib(i);
            b.lock().unwrap().push(n);
        });
        threads.push(t);
    }
    threads.into_iter().for_each(|t| t.join().unwrap());
    let _ = dbg!(a.lock().unwrap());
}

fn fib(n: u8) -> u64 {
    if n == 0 || n == 1 {
        1
    } else {
        fib(n - 1) + fib(n - 2)
    }
}

Playground

Possible output

Standard Error
   Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 1.58s
     Running `target/debug/playground`
[src/main.rs:18] a.lock().unwrap() = [
    1,
    5,
    8,
    13,
    55,
    3,
    144,
    233,
    377,
    610,
    987,
    1597,
    2584,
    4181,
    6765,
    2,
    1,
    21,
    89,
    34,
]
1 Like

Here for fun almost the same thing, but no synchronizing datastructure, just thread.join().

use std::thread;

fn main() {
    let res: Vec<u64> = (0u8..20)
        .into_iter()
        .map(|i| thread::spawn(move || fib(i)))
        // collect such that all threads are spawned before joining.
        .collect::<Vec<_>>()
        .into_iter()
        .map(|t| t.join().unwrap())
        .collect();
    dbg!(res);
}

fn fib(n: u8) -> u64 {
    if n == 0 || n == 1 {
        1
    } else {
        fib(n - 1) + fib(n - 2)
    }
}

Playground

This one also has an orderer output.

[src/main.rs:11] res = [
    1,
    1,
    2,
    3,
    5,
    8,
    13,
    21,
    34,
    55,
    89,
    144,
    233,
    377,
    610,
    987,
    1597,
    2584,
    4181,
    6765,
]

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.