Explain the concept of multi-threading. How do you handle race conditions in a low-level programming environment?