@Override
  public void join() throws MemberStartupException {

    try {
      if (Boolean.getBoolean(BYPASS_DISCOVERY_PROPERTY)) {
        synchronized (viewInstallationLock) {
          becomeCoordinator();
        }
        return;
      }

      SearchState<ID> state = searchState;

      long locatorWaitTime = ((long) services.getConfig().getLocatorWaitTime()) * 1000L;
      long timeout = services.getConfig().getJoinTimeout();
      logger.debug("join timeout is set to {}", timeout);
      long startTime = System.currentTimeMillis();
      long locatorGiveUpTime = startTime + locatorWaitTime;
      long giveupTime = startTime + timeout;
      int minimumRetriesBeforeBecomingCoordinator =
          getMinimumRetriesBeforeBecomingCoordinator(locators.size());

      for (int tries = 0; !isJoined && !isStopping; tries++) {
        logger.debug("searching for the membership coordinator");
        boolean found = findCoordinator();
        logger.info("Discovery state after looking for membership coordinator is {}",
            state);
        long now = System.currentTimeMillis();
        if (found) {
          logger.info("found possible coordinator {}", state.possibleCoordinator);
          if (localAddress.preferredForCoordinator()
              && state.possibleCoordinator.equals(localAddress)) {
            // if we haven't contacted a member of a cluster maybe this node should
            // become the coordinator.
            if (state.joinedMembersContacted <= 0 && ((now >= locatorGiveUpTime &&
                tries >= minimumRetriesBeforeBecomingCoordinator) ||
                state.locatorsContacted >= locators.size())) {
              synchronized (viewInstallationLock) {
                becomeCoordinator();
              }
              return;
            }
          } else {
            if (attemptToJoin()) {
              return;
            }
            if (isStopping) {
              break;
            }
            if (!state.possibleCoordinator.equals(localAddress)) {
              state.alreadyTried.add(state.possibleCoordinator);
            }
            if (System.currentTimeMillis() > giveupTime) {
              break;
            }
          }
        } else {
          if (state.locatorsContacted <= 0) {
            if (now > locatorGiveUpTime) {
              // break out of the loop and return false
              break;
            }
            tries = 0;
            giveupTime = now + timeout;
          } else if (now > giveupTime) {
            break;
          }
        }
        if (found && !state.hasContactedAJoinedLocator) {
          try {
            if (pauseIfThereIsNoCoordinator(state.possibleCoordinator.getVmViewId(),
                JOIN_RETRY_SLEEP)) {
              // since we were given a coordinator that couldn't be used we should keep trying
              tries = 0;
              giveupTime = System.currentTimeMillis() + timeout;
            }
          } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new MembershipConfigurationException(
                "Retry sleep interrupted. Giving up on joining the distributed system.");
          }
        }
      } // for

      if (!isJoined) {
        logger.debug("giving up attempting to join the distributed system after "
            + (System.currentTimeMillis() - startTime) + "ms");

        // to preserve old behavior we need to throw a MemberStartupException if
        // unable to contact any of the locators
        if (state.hasContactedAJoinedLocator) {
          throw new MemberStartupException("Unable to join the distributed system in "
              + (System.currentTimeMillis() - startTime) + "ms");
        }

        if (state.locatorsContacted == 0) {
          throw new MembershipConfigurationException(
              "Unable to join the distributed system. Could not contact any of the locators: "
                  + locators,
              state.lastLocatorException);
        }

        if (System.currentTimeMillis() > giveupTime) {
          throw new MembershipConfigurationException(
              "Unable to join the distributed system. Operation timed out");
        }
      }
      return;
    } finally {
      // notify anyone waiting on the address to be completed
      if (isJoined) {
        synchronized (localAddress) {
          localAddress.notifyAll();
        }
      }
      searchState.cleanup();
    }
  }
attempt to join the distributed system loop send a join request to a locator & get a response
<p>
If the response indicates there's no coordinator it will contain a set of members that have
recently contacted it. The "oldest" member is selected as the coordinator based on ID sort
order.
geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/gms/membership/GMSJoinLeave.java