Subj : Re: Deadlock theorem To : comp.programming.threads From : Uenal Mutlu Date : Wed May 04 2005 02:19 am "David Schwartz" wrote > > "Uenal Mutlu" wrote > > >> I agree that it's valid, just useless and dangerous. Please read my > >> criticism again. > > > Hmm. IMO it is by no means useless or dangerous. It is a very important > > feature, because it simplifies object locking very good; you don't need to > > check or unlock whether the object is already locked. In case it is > > "me" (the current thread) who already has it locked then a second > > lock request again by me simply increments the lock counter of the object > > and the lock is (again) granted. Of course one also can do these checkings > > also in the application code, but IMO it doesn't belong therein. > > It doesn't simplify anything. In order to write reliable code, you need > to know what locks you hold at the current level or at any lower levels. If > you know what locks you hold, you don't need a recursive lock. Just don't > acquire the lock again if you know you already hold it. > > As for it being dangerous, consider the following code: > > o1.Lock(); > while (o1.NotReady()) > { > o1.Unlock(); > Sleep(); > o1.Lock(); > } > o1.DoStuff(); > o1.Unlock(); > > This relies on the object being unlocked after the call to Unlock. With > recursive locks, this cannot be guaranteed. So recursive locks don't make > anything easier, you still need to know what locks you hold, and they create > new risks, the meaning of 'unlock' isn't always clear. I don't know what o1.NotReady() does. A typical snippet of my method would be like this: while (!IsEnd()) { Locker L(o1.LV); o1.DoStuff(); } By this, the object is locked only for the duration of one iteration of the loop. It is locked and unlocked permanently to make real shared (parallel) processing possible; ie. multiple threads can work on the same data (for example a vector) at the same time. This might sound slow, but it usually is not, even not on single CPU, and much faster especially if there are multiple CPUs available. BTW, IsEnd() here is for example to signal application quitting, and L is not further used; it is just a helper to perform the locking and unlocking within the block (ie. a C++ object with dtor) Another method would be: Locker L(o1.LV); while (!IsEnd()) { o1.DoStuff(); } Here the thread does one Lock() and keeps the object locked for a long period, all other threads needing access to this object must wait until this thread releases the lock. This method is IMO slower (in terms of application performance) than the above (regarded multiple threads need to access the object), although the other method does myriads of locking and unlocking whereas this one makes just one lock. As said: It is harmless (and there is no performance penaly) should DoStuff() lock the object again (b/c of the meaning of recursive locking discussed in prev postings. In both examples above DoStuff() does not need to lock, and it is harmless should it still do. Here I'm talking of the feature of my recursive locking method; the CriticalSection method of Win32 operates similar. .