One of the requirements for deadlock is mutual exclusion of resources: at most one process may own a resource at a time. We have looked at several ways that resources may be shared, and once a resource is shareable, access to it will not cause deadlock. For example, spooling jobs which are sent to the printer. Processes no longer need to aquire an exclusive lock on the printer in order to print something; they simply send the job to the print spooler. Or a filesystem on a disk; processes no longer require exclusive access to the disk drive, when they can go through the filesystem and share the physical disk with other processes.
Another condition is that processes hold and wait for resources. We can require that processes allocate all their resources immediately, and are not allowed to allocate new resources while holding on to other resources. This is typically too restrictive in general, though some systems use it.
Another possibility is to not allow processes to wait for resources. If a resource is busy the request simply fails, and returns an error code (instead of waiting). Many PC operating systems use this tactic.
We might also allow preemption of resources, though this could be awkward: if a process thinks that it owns a resource, snatching the resource (say a database record) from its sweaty grip may cause more problems than it solves (in terms of corrupted data, for example).
The circular wait condition is also a possible candidate for attack. We require that resources are always allocated in a particular order. In general a system may contain hundreds or thousands of resources, from files, to hardware, to semaphores, so imposing one global ordering is often impossible. In limited situations, however, like cooperating threads which use several semaphores, a good way to avoid deadlock it to decide upon a convention for the order in which resources should be locked.