Does it make sense to poll `pthread_mutex_trylock`?

370 Views Asked by At

Consider a multicore system with two threads running: thread A and thread B, which share some data. Thread A needs to do its job as fast as possible so we want it to be awake as often as possible.

Using spinlocks (either pthread's or implemented on top of atomic primitives) is discarded because we prefer thread B to sleep when waiting to get the lock.

Would it be an acceptable solution to mix busy wait (spin-lock) and "sleepy wait" the following way?:

pthread_mutex_t mutex; // Already initialized somewhere
SharedData data; // Structure for interthread communication

// Thread A (high throughput needed => spin)
while (appRunning) {
    while (pthread_mutex_trylock(&mutex) != 0) { } // Controversial point
    // Read/write to data
    pthread_mutex_unlock(&mutex);
}

// Thread B (should sleep during wait => standard locking)
while (appRunning) {
    pthread_mutex_lock(&mutex);
    // Read/write to data
    pthread_mutex_unlock(&mutex);
}

PS: I've tried to be generic, but if it matters, the actual scenario is that thread A is filling low-latency audio buffers according to what thread B asks for via the shared data and writes there some results. Thread B reacts to user input and it's acceptable for it to take a while to react as long as thread A doesn't underrun.

1

There are 1 best solutions below

2
On BEST ANSWER

Using a lock (mutex or spin lock) is not the right solution for low latency scenarios.
It'd be best if you could share only a small amount of data, and then you could just exchange the data in a single atomic instruction. Another solution is to have 2 data instances and exchange the pointer to it. If the above cannot work for you, and you have to fallback to a mutex or spin lock, you should prefer a spin lock.
With a spin lock the wake up time will be shorter as you don't have a context switch.
Thread A will have to wait (spinning) when thread B is holding the lock. And you can limit thread B to not acquiring the lock too often.
Thread B can try acquire the lock, not more than once in so often, and sleep for a bit if it fails.