Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Программирование под Unix/Linux > Адрес члена класса у 2 объектов класса


Автор: Soeth 5.11.2013, 18:47
Добрый вечер, столкнулся с непонятной проблемой, хотелось бы попросить помощи у знающих людей. )

Есть класс:

Код

class someClass {
  public:
    void function1() { std::cout << &var << std::endl; };

  private:
    int var;
};

Есть 2 потока, каждый создает свой объект типа someClass, а проблема заключается в том, что при вызове метода function1 что первый, что второй поток выдают один и тот же адрес переменной. Собственно в этом и проблема, 2 потока работают с одной переменной и одновременно меняют в ней данные.
Проблему можно решить синхронизацией потоков, к примеру мьютексами, но хотелось бы узнать у гуру, есть ли какая либо возможность 2 потокам одновременно работать с 2 объектами класса не блокируя первый пока работает второй ибо это не вариант если будет не 2, а 10 потоков работающих с этим объектом.
Спасибо за внимание.

Автор: Cheloveck 6.11.2013, 00:34
Код

#include <iostream>
#include <pthread.h>

class someClass {
  public:
    void function1() { std::cout << &var << std::endl; };
  private:
    int var;
};

void * test(void * ptr)
{
    someClass c;
    c.function1();
    pthread_exit(0); 
}

int main()
{
    pthread_t thread1, thread2;
    pthread_create(&thread1, NULL, test, NULL);
    pthread_create(&thread2, NULL, test, NULL);
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
}


Код

$ g++ test.cpp -lpthread
$ ./a.out 
0x7faf5bc81e90
0x7faf5b480e90


Цитата(Soeth @  5.11.2013,  19:47 Найти цитируемый пост)
что первый, что второй поток выдают один и тот же адрес переменной

 smile 

Автор: Soeth 6.11.2013, 02:00
Цитата(Cheloveck @ 6.11.2013,  00:34)
Код

#include <iostream>
#include <pthread.h>

class someClass {
  public:
    void function1() { std::cout << &var << std::endl; };
  private:
    int var;
};

void * test(void * ptr)
{
    someClass c;
    c.function1();
    pthread_exit(0); 
}

int main()
{
    pthread_t thread1, thread2;
    pthread_create(&thread1, NULL, test, NULL);
    pthread_create(&thread2, NULL, test, NULL);
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
}


Код

$ g++ test.cpp -lpthread
$ ./a.out 
0x7faf5bc81e90
0x7faf5b480e90


Цитата(Soeth @  5.11.2013,  19:47 Найти цитируемый пост)
что первый, что второй поток выдают один и тот же адрес переменной

 smile

Немного не правильно сформулировал проблему.
Если запускать 2 потока или один, которые используют объект класса someClass, и не дожидаясь завершения потоков (без pthread_join()) снова создавать потоки использующие данный класс, то тогда адрес var первого работающего потока будет такойже как адрес var второго потока.
Пример:
Код

#include <iostream>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <fstream>
#include <ctime>
#include <sys/timeb.h>
#include <string.h>

#define THREADS_COUNT 2

class someClass {
        public:
                void function1 () { std::cout << &var << std::endl; };
        private:
                int var;
};

int startedThreadCnt = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *testThread( void *ptr ) {
        pthread_detach(pthread_self());
        pthread_mutex_lock(&mutex);
        startedThreadCnt++;
        pthread_mutex_unlock(&mutex);
        someClass myObj;
        myObj.function1();
}
void foo() {
        pthread_t thread[THREADS_COUNT];
        int threadStatus[THREADS_COUNT];
        startedThreadCnt = 0;
        for (int i = 0; i < THREADS_COUNT; i ++) {
                threadStatus[i] = pthread_create(&thread[i], NULL, testThread, NULL);
                if (threadStatus[i] != 0) {
                        std::cout << strerror(threadStatus[i]) << std::endl;
                }
        }
        while (startedThreadCnt < THREADS_COUNT) {
                usleep(250 * 1000);
        }
}

int main () {
        for (int i = 0; i < 3; i ++) {
                foo();
                std::cout << "Pack: " << i << std::endl;
        }
        return 0;
}


Что выдает:
0xb6c7837c
0xb747937c
Pack: 0
0xb747937c
0xb6c7837c
Pack: 1
0xb747937c
0xb6c7837c
Pack: 2

Пока первая пачка потоков успевает отработать до запуска второй пачки потоков всё в порядке, но если к потоки будут работать к примеру по 5-10 секунд, а интервал между вызовами foo() будет 1-2 секунды, то получится, что все потоки будут работать с одним и тем же участком памяти.

Хотелось бы решить данную задачу без применения мьютексов и блокировки var на время работы одной пачки потоков т.к. в реальной задаче необходимо запускать эти "пачки" потоков в сравнительно небольшом интервале времени относительно времени выполнения потоковой ф-ии. Т.е. очередь потоков, ожидающих доступа к var будет только расти.

Автор: feodorv 6.11.2013, 20:30
Простите, но новые потоки просто занимают то же адресное пространство, что и завершившиеся старые, соответственно, адреса и совпадают. Это отнюдь не значит, что старые (от предыдущей пачки) потоки всё ещё работают, а новые (от новой пачки) внезапно начали работать с перекрывающимися областями памяти. Не нужна Вам здесь синхронизация.

Код

#include <stdio.h>
#include <stdlib.h>

int main( void )
{
  char *p;

  p = malloc( 10 );
  printf( "p1 = %p\n", p);
  free( p );

  p = malloc( 10 );
  printf( "p2 = %p\n", p);
  free( p );

  return 0;
}


Цитата

p1 = 00410350
p2 = 00410350

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)