Suppose you want addrspace.h to #include synch.h. But:
synch.h includes thread.h thread.h include addrspace.h
This forms a cycle - the compiler can't determine how much space to a class is going to need.
In order to do this, do not include synch.h. Instead, put statements that refer to the classes that you are going to use. For example:
class Lock; class Semaphore;addrspace.cc you'll have to include synch.h (which will be fine).
Using this method you can only use pointers to the classes whose definitions you have not included (because the compiler needs to know how much space to preserve for them and it knows that a pointer to any class uses the same amount of space). It doesn't know what the class looks like yet so it can not figure out how much space to preserve for the actual class - only a pointer to a class.