Explain the concept of multi-threading. What are the common challenges associated with concurrent programming, and how do you prevent race conditions?