When you have multiple shared resources (such as locks) and a thread needs to control exclusively more than one of them at the same time. You run the risk of deadlock when every thread is holding a resource that another thread needs. One way to avoid deadlock is to put a priority (perhaps arbitrarily) on the resources so that you cannot (or choose not to) claim a higher priority resource than one you are already holding. If you are holding a high-priority resource, you can claim a lower-priority resource. But if you are claiming a high-priority resource, you must first release all resources you hold with a lower priority. 5 Philosophers: 0: fork 1 and fork 0 1: fork 2 and fork 1 2: fork 3 and fork 2 3: fork 4 and fork 3 4: fork 0 and fork 4 This violates the priority given above since, in this scenario, 1 beats 0 which beats 4 which beats 3 which beats 2 which beats 1. So we do not a clear priority ranking here. But if change the forks of just one of the philosophers ("make him left-handed") 0: fork 0 and fork 1 1: fork 2 and fork 1 2: fork 3 and fork 2 3: fork 4 and fork 3 4: fork 0 and fork 4 0 beats 4 beats 3 beats 2 beats 1. Now every philosopher is obeying the maxim of not holding a lower-priority resource while requesting a higher-priority resource. Classic locking problem: Read Write problem. If you have any sort of shared file (say a database). Obviously any numbers can read the database at the same time. No one's changing anything, so you can have as many simultaneous readers as you want. However, you can't have more than one writer at a time. Because multiple writers can interfere with each other. Likewise, you can't have a writer and a reader in there together, for much the same reason. A reader trying traverse the database while a writer is in there changing stuff can lead to the reader returning the wrong answer. "Many read-one write" First approach READER: LOCK (lock) read information UNLOCK (lock) WRITER: LOCK (lock) write information UNLOCK (lock) Good: it works. The correct information is always returned. The database remains consistent. Bad: does not allow for multiple readers READER: read information WRITER: LOCK (lock) write information UNLOCK (lock) Good: can now have multiple readers Bad: allows a reader and a writer to be in there simultaneously Now, if you want to do something more sophisticated with locks, you have to put some thought and planning (and extra variables) into it. Locks are so crude that you really can't do some fancy scheduling like many read-one write without you also writing most of the code to enforce this. We will keep track of the number of readers (nr) the number of threads waiting to read (nrw) the number of writers (nw) the number of threads waiting to write (nww) READER: LOCK (adminlock) //when we're messing with our variables we don't another thread messing with our variables nrw++ if (nr==0 && nww==0 && nw==0) {nr++; nrw--; LOCK (lock); UNLOCK (adminlock) else if (nww==0 && nw==0) {nr++; nrw--; UNLOCK (adminlock);} else {UNLOCK (adminlock); LOCK (lock);} //this will require me to wait since a writer is already in there and already has it locked. read information LOCK (adminlock); nr--; if (nr==0) UNLOCK (lock); UNLOCK (adminlock); WRITER: LOCK (adminlock); if (nr==0) {nw++; UNLOCK (adminlock);LOCK (lock);} else {nww++; UNLOCK (adminlock); LOCK (lock); nww--; nw++} LOCK (lock); write information UNLOCK (lock); LOCK (adminlock); nw--; UNLOCK (adminlock); ^^^ This is wrong; I'll fix it. But the general idea is that locks are too crude a mechanism to do something like this. In fact, even when I get the code fixed, it still run into a problem of a thread sometimes unlocking a lock locked by someone else. (And locks don't usually work that way.) Semaphores, which we will get into next, are more powerful than locks and can handle this problem better...but you still have to keep track of who's using the resource and who's waiting for the resource. So there is still some tedium here and careful programming, but at least more complex things are doable.