def lock(self, atime=30, ltime=5, identifier=None):
        '''Context manager to acquire the namespace global lock.

        This is typically used for multi-step registry operations,
        such as a read-modify-write sequence::

            with registry.lock() as session:
                d = session.get('dict', 'key')
                del d['traceback']
                session.set('dict', 'key', d)

        Callers may provide their own `identifier`; if they do, they
        must ensure that it is reasonably unique (e.g., a UUID).
        Using a stored worker ID that is traceable back to the lock
        holder is a good practice.

        :param int atime: maximum time (in seconds) to acquire lock
        :param int ltime: maximum time (in seconds) to own lock
        :param str identifier: worker-unique identifier for the lock

        '''
        if identifier is None:
            identifier = nice_identifier()
        if self._acquire_lock(identifier, atime, ltime) != identifier:
            raise LockError("could not acquire lock")
        try:
            self._session_lock_identifier = identifier
            yield self
        finally:
            self._release_lock(identifier)
            self._session_lock_identifier = None
Context manager to acquire the namespace global lock.

        This is typically used for multi-step registry operations,
        such as a read-modify-write sequence::

            with registry.lock() as session:
                d = session.get('dict', 'key')
                del d['traceback']
                session.set('dict', 'key', d)

        Callers may provide their own `identifier`; if they do, they
        must ensure that it is reasonably unique (e.g., a UUID).
        Using a stored worker ID that is traceable back to the lock
        holder is a good practice.

        :param int atime: maximum time (in seconds) to acquire lock
        :param int ltime: maximum time (in seconds) to own lock
        :param str identifier: worker-unique identifier for the lock