Потокобезопасный вектор и строковый контейнер? - PullRequest
2 голосов
/ 25 августа 2010

Я опубликовал предыдущий вопрос "Ошибка сегмента при использовании std :: string на встроенной платформе Linux" , где я получил очень полезный совет. С тех пор я был в других проектах и ​​недавно вернулся к рассмотрению этого вопроса.

Повторюсь, я ограничен использованием кросс-компилятора arm-linux (версия 2.95.2), поскольку это то, что поставляется и поддерживается поставщиком встроенной платформы. Я понимаю, что проблема, скорее всего, связана с тем, что stdlib очень старый и не особо безопасен для потоков.

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

Невозможно использовать этот подход в моем приложении, так как я передаю контейнеры различным методам и классам. Я бы идеально хотел решить эту проблему или найти подходящую альтернативу. Я пробовал STLPort и стандартную библиотеку шаблонов SGI с теми же результатами. Я могу только предположить, что, поскольку они связаны очень старым gcc, они не могут решить проблему.

У кого-нибудь есть возможные рекомендации или решения? Или, может быть, вы можете предложить реализацию вектора (и строки), которую я могу добавить в свой код?

Заранее спасибо за любые рекомендации.

#include <stdio.h>
  #include <vector>
  #include <list>
  #include <string>

  using namespace std;
    /////////////////////////////////////////////////////////////////////////////

    class TestSeg
    {
     static pthread_mutex_t     _logLock;
     public:
      TestSeg()
      {
      }

      ~TestSeg()
      {
      }

      static void* TestThread( void *arg )
      {
       int i = 0;
       while ( i++ < 10000 )
       {
        printf( "%d\n", i );
        WriteBad( "Function" );
       }
       pthread_exit( NULL );
      }

      static void WriteBad( const char* sFunction )
      {
       //pthread_mutex_lock( &_logLock );
       //{

       printf( "%s\n", sFunction );
       string sKiller;     //       <----------------------------------Bad
       //list<char> killer;    //       <----------------------------------Bad
       //vector<char> killer;    //       <----------------------------------Bad

       //}
       //pthread_mutex_unlock( &_logLock );

       return;
      }

      void RunTest()
      {
       int threads = 100;
       pthread_t     _rx_thread[threads];
       for ( int i = 0 ; i < threads ; i++ )
       {
        pthread_create( &_rx_thread[i], NULL, TestThread, NULL );
       }

       for ( int i = 0 ; i < threads ; i++ )
       {
        pthread_join( _rx_thread[i], NULL );
       }
      }

    };

    pthread_mutex_t       TestSeg::_logLock = PTHREAD_MUTEX_INITIALIZER;

    int main( int argc, char *argv[] )
    {
     TestSeg seg;
     seg.RunTest();
     pthread_exit( NULL );
    }

Ответы [ 2 ]

6 голосов
/ 25 августа 2010

Проблема не в контейнерах, а в вашем коде.

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

Предположим, для демонстрации, что у вас есть поточно-ориентированная реализация, например, vector.

  • Тема 1: if (!vec.empty())
  • Тема 2: vec.clear();
  • Тема 1: foo = vec.front();

Это приводит к неопределенному поведению.

Проблема в том, что каждая операция в потоке-контейнере безопасна в значительной степени бессмысленно, потому что вы все равно должны иметь возможность заблокировать сам контейнер для нескольких операций подряд. Следовательно, вы будете блокировать различные операции, а затем снова блокировать все операции?

Как я уже сказал: совершенно ненужно.

2 голосов
/ 25 августа 2010

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

В вашей ситуации вы можете обернуть вектор STL в свой собственный векторный класс (вы можете рассмотреть Decorator ), который содержитмеханизм блокировки и обеспечивает логику блокировки / разблокировки при доступе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...