0

While working in a multi-threaded environment, then data sharing seems to be a good option to pass data between threads.

While working with real time systems it is apparently advisable to go with memory optimization.

So, in my scenario, I have one consumer and one producer. They share one queue of any data type e.g int queue. Now the producer generates data & copies the data to the queue and emits a signal to the consumer who is waiting for the signal as following:

thread 1:
pthread_mutex_lock(&mutex);
while (!condition)
    pthread_cond_wait(&cond, &mutex);
/* do something that requires holding the mutex and condition is true */
pthread_mutex_unlock(&mutex);

thread2:

pthread_mutex_lock(&mutex);
/* do something that might make condition true */
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);

Once the producer generates the data into the queue and emits a signal, then the consumer gets that signal & locks the queue to enter into a critical section.

Now, does the consumer need to copy that data or directly process that data in the critical section? Which option is advisable?

Consider a real time example, my producer thread generates data at every 50ms and as per code, locks the queue at every 50ms, copies data into the queue, emits a signal and unlocks.

Once the consumer receives the signal, it has to process the data. But, before processing the data, the consumer internally first locks the queue.

So, before the data is processed, should it be copied first or can it be directly processed and then unlocked ?

FYI, the consumer takes only 1ms of time to process.

In this scenario, is memory copying more efficient or is it the pointer to memory ?

  • 1
    please don't cross-post: stackoverflow.com/questions/49646845/… "Cross-posting is frowned upon as it leads to fragmented answers splattered all over the network..." – gnat Apr 4 '18 at 13:42
  • @gnat what if it is architecture level question & need to move to here. as it seems off-topic for Stackoverflow. please read last comment in stackoverflow.com/questions/49646845/… can you give me some better idea to move from Stackoverflow to here for more discussion on architecture level – Nishant Bijani A Apr 4 '18 at 13:48
  • What do you mean by "efficient"? I'd go for whatever way minimizes the amount of time I need to have the lock. Keep in mind that whatever your typical timings are, a system under load will not have things happen when you expect them to be. – 1201ProgramAlarm Apr 5 '18 at 4:08
  • inconsistency in time matters for me, as producer can produce input for queue inconsistently, which is totally dependent on device actually. so, here locking is required, but i am thinking about lockless queue now. as it seems efficient way of handling this kind of scenario. @1201ProgramAlarm any input for lockless ring buffer for this implementation or other way to handle this situation? – Nishant Bijani A Apr 5 '18 at 5:15
1

For this specific situation, I don't see why you need the "producer" and the "consumer" to be in separate threads. So if this specific situation is the only one you care about, then don't copy the data and don't thread.

A lot about designing programs is thinking about all the ways the program input could go wrong. If you know that the producer will only ever produce data every 50ms and you know that the consumer will only ever take 1ms to process that data, then you could integrate the consumer and producer into one thread and make everything simpler. However, if either of those things are in doubt, and the producer cannot wait on the consumer to finish (which it sounds like it can from the usage of a mutex lock), then you may need to thread.

Basically what you have right now acts like an unthreaded program, only more complicated. If you're just practicing writing code, then fine. However, if this needs to be threaded, what I would do is implement lockless circular queue. That way the producer can always put things into the queue (at least until it fills) and the consumer can work on the data without having to copy it. Not copying is generally more efficient than dereferencing a pointer, especially if you're doing things with lots of data.

0

The purpose of the lock is to prevent a race condition as the queue is being accessed. As such it should be no wider than necessary.

You may be prone to deadlocks if you are careless about this: if the processing part of the data has some asynchronous logic hidden in it that starts another thread that tries to queue something too.

By keeping the lock longer than needed, you defeat part of the purpose of using threads in the first place, stopping other threads that are waiting for the lock to become available from proceeding.

Just like you open the fridge, take what you need, close the fridge and then make breakfast, you should close a lock statement right after you are done doing what the lock is supposed to protect.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.