15 AnswersNew Answer
1. The thread constructor takes a function pointer/reference as first argument and then following that all arguments that should be passed to that function. The way member functions are implement in C++ is that they have a hidden first argument which is a pointer to the object this member function should be executed for. So the thread constructor always needs a pointer to an object of the class when using a member function of that class (to be precise this is only required for non-static member functions). Therefore it is possible to pass a pointer to an object obtained from new class_name() to the thread constructor. Be aware though that you should also delete that object at some point otherwise you will be leaking memory. 2. Well it makes sense to first create both threads because how should the consume function receive anything in the queue when you haven't even called the produce function. By the way it does not matter in which order you join the threads so that is up to you.
Ketan Lalcheta In lines 53 and 55 you have to pass &q to the thread constructor. Then the program will work. It will still have no output though. If you want output (which I assume) you should swap line 54 with line 55. Another thing I noticed is that you initialize the random number generator with the current time in function produce. Since this program executes really fast you will most of the time get the same numbers in the two times you execute your two functions.
3. To fix the issue with the random numbers you can just call srand once at the beginning of your program in main() and then you will get different numbers.
Since you call join on the threads inside the for loop the loop will not continue with the next iteration until the threads finished execution. (This is what the join function is intended to do: it waits until the thread finishes execution) If you want to have some random behavior you have several options. 1. You could just call detach on the threads instead of join. You should run the loop many times to see this effect. Using detach is however very dangerous and you will see the code crashing during execution sometimes and sometimes not. Of course you can make the main thread wait a few milliseconds and hope that the threads have finished but that is still not safe. 2. The in my opinion better way to do this is to have the threads stored outside the for loop in for example a vector and then after the loop join all of them. This way you will actually get the kind of randomness you were talking about and it will work normally all the times. Like this: https://code.sololearn.com/cA2a72a9a235/?ref=app
Ketan Lalcheta I made a version of this which displays the size of the queue after an element was "produced". It shows really nice the randomness when the stack is growing and shrinking. I thought you might be interested in seeing this: https://code.sololearn.com/c8a17a14A22A/?ref=app
I think I would have to quote a bit more from that site to make it extra clear. It says "The function returns when the thread execution has completed. This synchronizes the moment this function returns with the completion of all the operations in the thread: This blocks the execution of the thread that calls this function until the function called on construction returns (if it hasn't yet)." You can also read that here: https://www.cplusplus.com/reference/thread/thread/join/ So it says that the join function blocks the execution of the thread that calls it (which in this case is our main thread). This means that in the for loop when calling join the execution of the main thread and therefore the execution of the for loop is blocked (i.e. stopped) until the produce/consume function have finished exection. To the queue: it is correct that you do not really need a queue if you only have the for loop with calling join on the threads because you will always have at most one element in the queue.
Ketan Lalcheta Yes this is incorrect. You can quite easily see this with a code like this one: https://code.sololearn.com/c5a8A236962a/?ref=app
Ketan Lalcheta I don't know the exact execution time limit on SL but this code should also work with longer sleep duration on a system without time limit. So you can maybe try the code on your PC or another online compiler. In the code I posted a few hours ago (where the threads are stored in a vector) they can actually execute in parallel. In this special case that won't have much of an advantage because the function in the thread does very little work and also uses a mutex for all it's work. This means that always only one thread can do actual work. The others just wait until they get notified. But if they would do more work on there own and only need the mutex for a short time then they would do meaningful work in parallel. Since we join all of the threads after the for loop that is the point at which we have to wait until all threads finished execution. So if two threads each wait for 1 second this won't take 2 seconds but approximately 1 second since the waiting is "done" in parallel.
Thanks Hape for details... It is helpful. I have still few questions: 1. Is class object required as pointer rather than mere object ? If I recall correctly, I used to pass temp object to thread like new test (assume test as class and constructor does not takes argument). Is this correct or I forgot something? To conclude, thread object construction always need class pointer for member function ? 2. Yes , joining threads post both created gives output. But why I need to create both the thread firsts before joining ? 3. I changed for loop count to 200 and still code produce the same number as output for all 400 times
Thanks Hape ... It works and got it clear to me as well... One last question on this one : I am creating thread object inside for loop. So, t1 and t2 is having scope inside for loop brackets only... Does this mean that for loop will not go to next iteration till thread object function execution is over. I feel it's no because for loop can continue without completion of threads but main thread can't complete till all the joined threads are not over. With this behaviour, I was expecting to have some random behaviour like more production and less consumption or vice versa. But both thread operates one by one. In such case, queue size is of no use... How to achieve this?
Yes detach is dangerous and would opt for vector... But this ask for extra space of vector allocation... Is there any other way to utilise queue capacity effectively ? Regarding for loop iteration , I am not sure but I believe that it should go ahead to next iteration without completion. It's not like entire main thread is complete by going to next iteration... It's just for loop iteration which is part of main thread. Main thread should wait for all other joined thread but not iteration... This is just my thoughts, not sure on this... And yes once again , many thanks for your time and help... It really help. Many things got clear today to me
Ketan Lalcheta I am not quite sure what you mean by "utilise queue capacity effectively". Regarding the for loop I think you are wrong as I mentioned earlier. The documentation for the join function starts like this: "The function returns when the thread execution has completed" (from cplusplus.com). So i think it is clear that the for loop does wait for the threads to be executed.
Yes , that size display is great... Regarding queue capacity, I was saying that queue capacity is set as 20 and it does not solve any purpose if vector is not used and only for loop is there. It says function return , not iteration...
I tried to create different scenarios but could not prove it through code.... I just had belive as below : Main thread calls different threads... Main thread can not be completed if any of the JOINED thread execution is pending for completion. For below sequence of code: Main starts Thread t1 created Thread t2 created code lines 4 to 10 t1 joined t2 joined Code lines 13 to 20 End of main function In this case , line 2 and 3 that is thread object created will start executing thread function... Also main function will execute code line 4 to 10 same time. Now , thread joined. This means that main has to wait for completion of t1 and t2 but it does not block code line 13 to 20 13 to 20 done and simultaneously, thread is also executing thread functions Now still thread function is not over , main thread has to wait till it is over due to join function. Join does not means that code line 13 to 20 does not execute till thread function are not over This is my thoughts which seems incorrect now
Yeah I think it was my perception.. Whats the use of thread then if it's not parallel and blocking the same... Just to check , I changed sleep time to 500 from 100 and thread output on android app version is not complete. Seems issue of this app