class_docstr: Distributed Centralized Lock
  
  Parameters
  ----------
  names
      Names of the locks to acquire. Choosing the same name allows two
      disconnected processes to coordinate a lock.
  client
      Client to use for communication with the scheduler.  If not given, the
      default global client will be used.
  
  Examples
  --------
  >>> lock = MultiLock(['x', 'y'])  # doctest: +SKIP
  >>> lock.acquire(timeout=1)  # doctest: +SKIP
  >>> # do things with protected resource 'x' and 'y'
  >>> lock.release()  # doctest: +SKIP
code: def __enter__(self):
      self.acquire()
      return self
  
imports: from __future__ import annotations
  import asyncio
  import logging
  import uuid
  from collections import defaultdict
  from collections.abc import Hashable
  from dask.utils import parse_timedelta
  from distributed.client import Client
  from distributed.utils import TimeoutError, log_errors, wait_for
  from distributed.worker import get_worker
label_desc: Use image node_id 5 for calling the MultiLock obj's underlying member method code with example usage: obj.__enter__() and returns: self