So when programming with locks as a synchronization primitives you can ensure no deadlock by ensuring that an ordering exists on the locks and that all acquires of the locks happen in that order (which really just needs to be a well founded quasi-order). This lends itself to lots of different kinds of solutions to dead lock. You can bake this into the type system itself by demanding that locks have a number associated with them at the type level and that acquiring a lock demands that an already acquired lock of a higher level be passed to it.
Deadlock can also occur when working with channels however. For instance I could wait on receiving something on a channel and never ever get it. I could also, in the case of $\pi$-calculus get stuck waiting on something to send too. Additionally cycles of waiting to receive things can occur which is more like the deadlock that occurs with locks. This leads me to think that some kind of ordering constraint plus a constraint that rules there not being an active sender/reciver on the other side might be helpful.
Is there a similarly helpful condition one can impose on channels to disallow deadlock? Is there a process algebra (weather it uses channels or not) that does not have dead lock?