use defer to ensure that unlock is called