Rick,
Threads are not "forked()" they are "spawned" and in this case, in my opinion,
language matters because something that is forked is practically gone down
the forking path and is on its own. Threads are still children of the main
process, and can detach or reattach. If these concepts are not clear, you can
get really confused while writing code.

The mutexes and semaphores are not a POSIX thread thing, but a general
construct. I recently tried, and succeeded, implementing a distributed parallel
mutex and semaphore. The concept is generic.

Semaphores/mutexes are just one way to synchronize threads. As I had said in
the past, I use pipes with a select() system call to monitor the pipes for
changes to achieve the same effect more generically. I did this for a sound
application, which requires good real-timeness. I can share pseudocode and
timing diagram if anyone is interested.