Race conditions in single-threaded JavaScript are possible due to asynchronous code execution using callbacks, promises, and async/await. Common concurrency problems include race conditions, deadlocks, and resource starvation. Potential solutions include synchronization primitives like mutexes and semaphores, resource locking, and flow commutation to control the order of asynchronous operations.