Locking doesn't restrict access to the synchronizing object itself in any way.
X.ToString () will not block because another thread has called lock (x); both threads must call lock (x) in order for blocking to occur.