Explain the concept of multi-threading. How do you handle thread safety and prevent race conditions in C# or Java?