Subj : Re: Challenge: Multithreading & Synchronization To : comp.programming.threads From : Uenal Mutlu Date : Fri May 20 2005 08:02 pm "Maciej Sobczak" wrote > > Uenal Mutlu wrote: > > >>What about the multithreaded program, where all threads use stdout to > >>log their actions? > >> > >>puts("I'm doing this."); > >>puts("I'm doing that."); > >> > >>Which "case" would you apply here? > > > > You have to ask yourself especially the following question: > > "which object(s) am I sharing among multiple threads?" > > The terminal? Of course: Question: Is in your application the terminal shared by multiple threads? Answer: YES Then: make the terminal lockable How: of course by a mutex; see below > > Then the solution will be simple. > > Tell me! :-) > In fact, this trap is not about "which object are you sharing", but > about what is the sequence of activities you want to perform. > This is exactly what you don't see. > > > It works. What do you think does "exclusive access to the object" mean? > > It is not the question of what it does mean, but what it doesn't. > > > Try this: > > > > void f() > > { > > Locker L(vec.m); > > for (size_t i = 0; i < vec.size(); i++) > > cout << vec[i].myfield << ... > > } > > Above, locking on the vector is not sufficient, because it does *not* > guarantee that the vector's content will be printed continuously on the > output, because there might be other functions that will print something > else at the same time (other vectors?), giving you something between > garbage and core dump, inclusive. > > Again - think in terms of actions, not in terms of objects > (multithreading is about "doing", not about "values"). Then you will > maybe discover that your concept of embedding mutexes in all value > objects brings you nowhere. Time will prove you wrong. > But sadly speaking, I doubt in any chance of such happy end. Sorry, but if you think you know it better then I wonder why on hell are you keep asking me then even such a really simple basic problem, ie. the solution is really that simple and obvious. But, in case you really don't know: In your case actually you want to use 2 objects in a shared manner: 1) the output stream 2) the vector Using the "mutex per object" method gives you a simple and elegant solution: void f() { // lock both applying the rules of the deadlock theorem (ie. lock in right order): Locker lo(myos.m); Locker lv(vec.m); // do what you want: for (size_t i = 0; i < vec.size(); i++) myos << vec[i].myfield << ... } Some people will argue that just 1 mutex would be sufficient. Let them think so. The above is the recommended method. .