docs: public void unlock(Locker locker)
      {
          // All access to the lockTable must be synchronized, even just checking
          // the size.  Since this method is for a transaction and not a bean
          // type, it is difficult to tell when no Option A caching has been
          // involved.  The performance impact should be minimal.         d114715
          synchronized (lockTable)
          {
              // If there are not locks, then don't do anything, including trace
              // entry/exit.  Either there are no Option A beans, or there just
              // don't happen to be any locks.
              if (lockTable.size() == 0)
              {
                  return;
              }
  
              if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                  Tr.entry(tc, "unlock", locker);
  
              // Loop through all of the locks in the table, and unlock any
              // locks held by the locker (containerTx).  The containerTx
              // holds the lock if it is the locker or if it is the holder
              // on a true Lock object.
              Enumeration lockNames = lockTable.keys();
  
              while (lockNames.hasMoreElements())
              {
                  Object lockName = lockNames.nextElement();
  
                  Object o = lockTable.get(lockName);
                  if (o == locker)
                  {
                      unlock(lockName, locker);
                  }
                  else if (((LockProxy) o).isLock())
                  {
                      if (((Lock) o).isHolder(locker))
                      {
                          unlock(lockName, locker);
                      }
                  } // if isLock()
              } // while lockNames
  
              if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                  Tr.exit(tc, "unlock");
  
          } // synchronized
      }