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
docstr: Acquire the lock
  
  Parameters
  ----------
  blocking : bool, optional
      If false, don't wait on the lock in the scheduler at all.
  timeout : string or number or timedelta, optional
      Seconds to wait on the lock in the scheduler.  This does not
      include local coroutine time, network transfer time, etc..
      It is forbidden to specify a timeout when blocking is false.
      Instead of number of seconds, it is also possible to specify
      a timedelta in string format, e.g. "200ms".
  num_locks : int, optional
      Number of locks needed. If None, all locks are needed
  
  Examples
  --------
  >>> lock = MultiLock(['x', 'y'])  # doctest: +SKIP
  >>> lock.acquire(timeout="1s")  # doctest: +SKIP
  
  Returns
  -------
  True or False whether or not it successfully acquired the lock
docstr_tok: ["Acquire","the","lock","Parameters","--","--","--","--","--","blocking",":","bool",",","optional","If","false",",","do","n't","wait","on","the","lock","in","the","scheduler","at","all",".","timeout",":","string","or","number","or","timedelta",",","optional","Seconds","to","wait","on","the","lock","in","the","scheduler",".","This","does","not","include","local","coroutine","time",",","network","transfer","time",",","etc","..","It","is","forbidden","to","specify","a","timeout","when","blocking","is","false",".","Instead","of","number","of","seconds",",","it","is","also","possible","to","specify","a","timedelta","in","string","format",",","e.g",".","``","200ms","''",".","num_locks",":","int",",","optional","Number","of","locks","needed",".","If","None",",","all","locks","are","needed","Examples","--","--","--","--",">",">",">","lock","=","MultiLock","(","[","'","x","'",",","'","y","'","]",")","#","doctest",":","+SKIP",">",">",">","lock.acquire","(","timeout=","''","1s","''",")","#","doctest",":","+SKIP","Returns","--","--","--","-","True","or","False","whether","or","not","it","successfully","acquired","the","lock"]
code: def acquire(self, blocking=True, timeout=None, num_locks=None):
      """Acquire the lock
  
      Parameters
      ----------
      blocking : bool, optional
          If false, don't wait on the lock in the scheduler at all.
      timeout : string or number or timedelta, optional
          Seconds to wait on the lock in the scheduler.  This does not
          include local coroutine time, network transfer time, etc..
          It is forbidden to specify a timeout when blocking is false.
          Instead of number of seconds, it is also possible to specify
          a timedelta in string format, e.g. "200ms".
      num_locks : int, optional
          Number of locks needed. If None, all locks are needed
  
      Examples
      --------
      >>> lock = MultiLock(['x', 'y'])  # doctest: +SKIP
      >>> lock.acquire(timeout="1s")  # doctest: +SKIP
  
      Returns
      -------
      True or False whether or not it successfully acquired the lock
      """
      timeout = parse_timedelta(timeout)
  
      if not blocking:
          if timeout is not None:
              raise ValueError(
                  "can't specify a timeout for a non-blocking call"
              )
          timeout = 0
  
      result = self.client.sync(
          self.client.scheduler.multi_lock_acquire,
          locks=self.names,
          id=self.id,
          timeout=timeout,
          num_locks=num_locks or len(self.names),
      )
      self._locked = True
      return result
  
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 2 for calling the MultiLock obj's underlying member method code with example usage: obj.acquire(blocking, timeout, num_locks) and returns: result