Synchronize operations that change socket state

It is possible to for example call disconnect from two threads at once.
This can lead to an inconsistent state if both threads attempt to
release the same object twice. Protect against these issues by wrapping
all operations that change the internal state of the socket with a
synchronization block.

Signed-off-by: Marcus Karlsson <mk@acc.umu.se>