Thread A acquires the lock, reads the value (1), posts to the API, increases to 2, and the scheduler suspends it. Thread B is given some CPU time, so it tries to acquire the lock. But the lock hasn't been released yet by Thread A, so Thread B sits and waits. The scheduler might notice this, and quickly decide to switch back to Thread A.
Thread A saves 2, and releases the lock, making it available to all other threads.
At this point, whether the lock is acquired again by Thread A, or by Thread B (because the scheduler might have decided to switch again), is not important. The procedure will always be carried out correctly, since the lock makes sure that when a thread reads a value, it has to complete the procedure (ping API, increment, and save) before any other thread can read the value as well.
There are a multitude of different locks available in the standard library. I definitely encourage you to read up on them to understand all the perils you might encounter when coding multithreaded code, and how to solve them.
Let's now talk about deadlocks.