If concurrent logic may need to execute on different machines, then processes should be used.
If concurrent logic needs to share complex data structures in memory, then threads should be used.
Not all concurrent logic fall cleanly into one or the other category. As a result, some concurrent logic can be implemented by multi-process or multi-thread solutions.
It should be noted that concurrent logic can also be implemented by a single thread of a single process. A prime example is the proxy server squid. It has to maintain multiple simultaneous connections and caching, and yet it is implemented (at least was implemented) by a single thread.
In terms of debugging, a multi-threading and multi-processing each has its challenges. The interaction of threads, however, can lead to unreproduceable and sporadic symptoms due to improper sharing of variables and objects. The interaction of processes, however, generally do not produce the same sort of bugs. This safety is paid by a somewhat hefty price of resources and the inability to share data.
In some smaller systems, multi-processing is not even an option. For example, a microcontroller often lacks the resources to support multiple processes. However, multi-threading can be supported by relatively little resources, to the point that 4kB of RAM is sufficient for simpler systems. Multi-threading is still better than no concurrent logic.