I think the biggest gotcha is forgetting if multiple areas can be starting threads, as you may have race conditions, as one section may be synchronized but if there is another entry point you will have a hard problem to track down.
But, the hardest part is knowing when to use multi-threading. It isn't perfect for every situation.
What parameters should be passed in, and how few global variables can you get away with.
I think there is a great deal of good ideas coming from functional programming, to limit side effects, as you start to learn that largely global variables can be bad, if they are changeable by many different threads.
Debugging when you have multiple threads will also be a challenge, depending on the language you use, for example, using a C debugger on unix is not fun, but Visual Studio makes it easier.