Explain the concept of thread safety. How do you design a multi-threaded application to avoid race conditions and deadlocks?