static public function release($key)
    {
        $keyMD5 = md5(self::$keyPrefix . serialize($key));
        if (!isset(self::$data[$keyMD5])) {
            throw new \Exception('A lock name "' . $key . '" does not exists in current process!');
        }
        $dir = self::getLocksDir();
        if (!is_dir($dir)) {
            return;
        }
        set_error_handler(function($errno, $errstr) {
            throw new \Exception($errstr);
        });
        try {
            if (flock(self::$data[$keyMD5], LOCK_UN) && fclose(self::$data[$keyMD5])) {
                try {
                    $filename = $dir . $keyMD5 . '.lock';
                    $tempFilename = $filename . '.' . md5(uniqid() . rand(0, 999999));
                    $renameResult = rename($filename, $tempFilename);
                    if ($renameResult) {
                        unlink($tempFilename);
                    }
                } catch (\Exception $e) {
                    // Don't care whether the rename is successful
                }
                unset(self::$data[$keyMD5]);
                restore_error_handler();
                return;
            }
        } catch (\Exception $e) {
            restore_error_handler();
            throw new \Exception('Cannot release the lock named "' . $key . '". Reason: ' . $e->getMessage());
        }
        restore_error_handler();
        throw new \Exception('Cannot release the lock named "' . $key . '"');
    }