use internal lock instead of synchronized method to encapsulate locking