code: public <T> T runBusLockedDeviceAction(final I2CDevice device, final Callable<T> action) throws IOException {
          if (action == null) {
              throw new NullPointerException("Parameter 'action' is mandatory!");
          }
  
          testForProperOperationConditions(device);
  
          try {
              if (accessLock.tryLock(lockAquireTimeout, lockAquireTimeoutUnit)) {
                  try {
                      testForProperOperationConditions(device);
  
                      selectBusSlave(device);
  
                      return action.call();
                  } finally {
                      accessLock.unlock();
                  }
              }
          } catch (InterruptedException e) {
              logger.log(Level.FINER, "Failed locking I2CBusImpl-" + busNumber, e);
              throw new RuntimeException("Could not obtain an access-lock!", e);
          } catch (IOException e) { // unwrap IOExceptionWrapperException
              throw e;
          } catch (RuntimeException e) {
              throw e;
          } catch (Exception e) { // unexpected exceptions
              throw new RuntimeException(e);
          }
          throw new RuntimeException("Could not obtain an access-lock!");
      }
docs: Selects a device on the bus for an action, and locks parallel access around file descriptor operations.
  Multiple bus instances may be used in parallel, but a single bus instance must limit parallel access.
  <p>
  The timeout used for the acquisition of the lock may be defined on getting the I2CBus from I2CFactory.
  <p>
  The 'run'-method of 'action' may throw an 'IOExceptionWrapperException' to wrap IOExceptions. The wrapped IOException is unwrapped by this method and rethrown as IOException.
  
  @param <T> The result-type of the method
  @param device Device to be selected on the bus
  @param action The action to be run
  @throws RuntimeException thrown by the custom code
  @throws IOException see method description above
  @see I2CFactory#getInstance(int, long, java.util.concurrent.TimeUnit)