Как я использую произвольную строку в качестве блокировки в C++?

Одна вещь, которую вы можете сделать, это подавить предупреждение, используя аннотацию для « Unchecked casts ».

Проверьте пример:

@SuppressWarnings("unchecked") // This would be helpful for lint warnings for casts.
@NonNull
@Override
public  T create(@NonNull Class modelClass) {
    if (modelClass.isAssignableFrom(clubPageViewModel.class)) {
        // Or better use here if it doesn't provides error @SuppressWarnings("unchecked")
        return (T) new clubPageViewModel(mDataSource);
    }
    throw new IllegalArgumentException("Unknown ViewModel class");
}

Итак, что делает эта аннотация @SuppressWarnings ?

По сути, это означает, что Предупреждения именованного компилятора должны подавляться в аннотированном элементе (и во всех элементах программы, содержащихся в аннотированном элементе) .

Обратите внимание, что набор предупреждений, подавляемых в данном элементе, является расширенным набором предупреждений, подавляемых во всех содержащих элементах.

Например, , если вы аннотируете класс для подавления одного предупреждения и аннотируете метод для подавления другого, оба метода будут подавлены в методе.

В целях стиля программисты всегда должны использовать эту аннотацию для наиболее глубоко вложенного элемента, где она эффективна. Если вы хотите подавить предупреждение в конкретном методе, вы должны аннотировать этот метод, а не его класс.

blockquote>

Подробнее об этой аннотации можно прочитать здесь .

8
задан eschercycle 3 October 2008 в 18:34
поделиться

6 ответов

Вы могли сделать что-то подобное тому, что Вы имеете в своем вопросе, но вместо единственного global_key_map имеют несколько (вероятно, в массиве или векторе) - какой используется, определяется некоторой простой хеш-функцией на строке.

Тот путь вместо единственной глобальной блокировки, Вы распространяете это по нескольким независимым.

Это - шаблон, который часто используется в средствах выделения памяти (я не знаю, имеет ли шаблон имя - он должен). Когда запрос входит, что-то определяет, из какого пула выделение прибудет (обычно размер запроса, но другие параметры могут включить в также), затем только, что пул должен быть заблокирован. Если запрос выделения входит от другого потока, который будет использовать другой пул, нет никакой конкуренции за блокировку.

12
ответ дан 5 December 2019 в 09:26
поделиться

Это будет зависеть от платформы, но два метода, которые я попробовал бы, будут:

  • Используйте названное взаимное исключение/объекты синхронизации, где имя объекта = Ключ
  • Используйте основанную на файловой системе блокировку, где Вы пытаетесь создать несовместно используемый временный файл с ключевым именем. Если это уже будет существовать (=already заблокированный), то это перестанет работать, и необходимо будет опросить для повторения

Оба метода будут зависеть от детали Вашей ОС. Экспериментируйте и посмотрите который работы..

2
ответ дан 5 December 2019 в 09:26
поделиться

Возможно, std::map<std::string, MutexType> был бы тем, что Вы хотите, где MutexType тип взаимного исключения, которое Вы хотите. Необходимо будет, вероятно, перенести доступы к карте в другом взаимном исключении, чтобы удостовериться, что никакой другой поток не вставляет одновременно (и не забудьте выполнять проверку снова после того, как взаимное исключение заблокировано, чтобы гарантировать, что другой поток не добавил ключ при ожидании на взаимном исключении!).

Тот же принцип мог относиться к любому другому методу синхронизации, такому как критический раздел.

2
ответ дан 5 December 2019 в 09:26
поделиться

Гранулярность повышения и блокирует все диапазоны ключей

Это - вариация на ответ B Mike, где вместо того, чтобы иметь несколько жидкостей блокируют карты, у Вас есть единственный фиксированный массив блокировок, которые относятся к диапазонам ключей вместо единственных ключей.

Упрощенный пример: создайте массив 256 блокировок при запуске, затем используйте первый байт ключа для определения индекса блокировки, которая будет получена (т.е. всеми ключами, запускающимися с 'k', будут охранять locks[107]).

Для поддержки оптимальной пропускной способности, необходимо проанализировать распределение ключей и состязательного уровня. Преимущества этого подхода являются нулевыми динамическими выделениями и простой очисткой; Вы также избегаете двухступенчатой блокировки. Оборотная сторона является потенциальными состязательными пиками, если ключевое распределение становится скошенным со временем.

2
ответ дан 5 December 2019 в 09:26
поделиться

После размышления об этом мог бы пройти примерно так другой подход:

  • В handleRequest, создайте a Callback это делает фактическую работу.
  • Создайте a multimap<string, Callback*> global_key_map, защищенный взаимным исключением.
  • Если поток видит это key уже обрабатывается, это добавляет Callback* к global_key_map и возвраты.
  • Иначе это сразу называет свой обратный вызов и затем называет обратные вызовы, которые собрались тем временем для того же ключа.

Реализованный что-то вроде этого:

LockAndCall(string key, Callback* callback) {
    global_lock.Lock();
    if (global_key_map.contains(key)) {
        iterator iter = global_key_map.insert(key, callback);
        while (true) {
            global_lock.Unlock();
            iter->second->Call();
            global_lock.Lock();
            global_key_map.erase(iter);
            iter = global_key_map.find(key);
            if (iter == global_key_map.end()) {
                global_lock.Unlock();
                return;
            }
        }
    } else {
        global_key_map.insert(key, callback);
        global_lock.Unlock();
    }
}

Это имеет преимущество освобождения, распараллеливает, который иначе ожидал бы блокировки ключа, но кроме которого это - в значительной степени то же как наивное решение, которое я отправил в вопросе.

Это могло быть объединено с ответами, данными Mike B и Constantin, все же.

0
ответ дан 5 December 2019 в 09:26
поделиться
      /**
      * StringLock class for string based locking mechanism
      * e.g. usage
      *     StringLock strLock;
      *     strLock.Lock("row1");
      *     strLock.UnLock("row1");
      */
      class StringLock    {
      public:
          /**
           * Constructor
           * Initializes the mutexes
           */
          StringLock()    {
              pthread_mutex_init(&mtxGlobal, NULL);
          }
          /**
           * Lock Function
           * The thread will return immediately if the string is not locked
           * The thread will wait if the string is locked until it gets a turn
           * @param string the string to lock
           */
          void Lock(string lockString)    {
              pthread_mutex_lock(&mtxGlobal);
              TListIds *listId = NULL;
              TWaiter *wtr = new TWaiter;
              wtr->evPtr = NULL;
              wtr->threadId = pthread_self();
              if (lockMap.find(lockString) == lockMap.end())    {
                  listId = new TListIds();
                  listId->insert(listId->end(), wtr);
                  lockMap[lockString] = listId;
                  pthread_mutex_unlock(&mtxGlobal);
              } else    {
                  wtr->evPtr = new Event(false);
                  listId = lockMap[lockString];
                  listId->insert(listId->end(), wtr);
                  pthread_mutex_unlock(&mtxGlobal);
                  wtr->evPtr->Wait();
              }
          }
          /**
          * UnLock Function
          * @param string the string to unlock
          */
          void UnLock(string lockString)    {
              pthread_mutex_lock(&mtxGlobal);
              TListIds *listID = NULL;
              if (lockMap.find(lockString) != lockMap.end())    {
                  lockMap[lockString]->pop_front();
                  listID = lockMap[lockString];
                  if (!(listID->empty()))    {
                      TWaiter *wtr = listID->front();
                      Event *thdEvent = wtr->evPtr;
                      thdEvent->Signal();
                  } else    {
                      lockMap.erase(lockString);
                      delete listID;
                  }
              }
              pthread_mutex_unlock(&mtxGlobal);
          }
      protected:
          struct TWaiter    {
              Event *evPtr;
              long threadId;
          };
          StringLock(StringLock &);
          void operator=(StringLock&);
          typedef list TListIds;
          typedef map TMapLockHolders;
          typedef map TMapLockWaiters;
      private:
          pthread_mutex_t mtxGlobal;
          TMapLockWaiters lockMap;
      };
0
ответ дан 5 December 2019 в 09:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: