Вы звоните m()
в главном потоке. Чтобы вызвать его в отдельном потоке, вам необходимо переопределить метод run()
в ваших классах потоков и вызвать m()
из run()
.
Как только вы исправите это, очень маловероятно, чтобы оба потока вошли в блок одновременно, вплоть до наносекунд. Вы можете попробовать создать множество потоков и циклов выполнения, чтобы увидеть проблемы параллелизма. Но поскольку a
является статическим, «новый» объект быстро перезапишет старый экземпляр.
Посмотрите на этот ответ , чтобы понять синхронизацию в одноэлементной структуре.
Указатель на пустоту, void*
может указать на любой объект:
int a = 5;
void *p = &a;
double b = 3.14;
p = &b;
Вы не можете разыменовать, увеличить или постепенно уменьшить тот указатель, потому что Вы не знаете то, что вводит Вас, указывают на. Идея - это void*
может использоваться для функций как memcpy
это просто копирует блоки памяти вокруг и не заботится о типе, что они копируют.
Это - просто универсальный указатель, используемый для передачи данных, когда Вы не знаете тип. Необходимо бросить его к корректному типу для использования его.
Это - необработанный указатель на место в памяти. Это не позволяет адресной арифметики с указателями как символ * или интервал *.
Вот некоторые примеры использования
Это - указатель на что-либо - просто блок памяти, которую можно играть с - мог бы быть объект, мог бы быть символ. Необходимо бросить, чтобы сделать что-либо полезное с ним.
Создание от моей предшествующей регистрации...
ВНИМАНИЕ: Все адреса памяти здесь являются вымышленными. Я просто составляю их, чтобы проиллюстрировать тезис.
Данный:
int data[] = {10,11,12};
Мы теперь имеем:
0xffff0000-0xffff0003 with a value of (int)(10)
0xffff0004-0xffff0007 with a value of (int)(11)
0xffff0008-0xffff000b with a value of (int)(12)
(Я не собираюсь входить в обратный порядок байтов по сравнению с порядком байтов с прямым порядком байтов здесь.)
Если мы имеем:
int * p = data;
Мы теперь имеем другую ячейку памяти где-то в другом месте, говорим:
0xaaaa0000-0xaaaa0003 with a value of (int*)0xffff0000
Мы можем использовать p[1] [или * (p + 1)] для обращения к * (интервал*) (0xffff0004) [=11] как sizeof (интервал) =4 и 0xffff0000+sizeof (интервал) = 0xffff0004.
Если мы имеем:
void * v = data;
Мы теперь имеем другую ячейку памяти где-то в другом месте, говорим:
0xbbbb0000-0xbbbb0003 with a value of (void*)0xffff0000.
Однако пусто не имеет, любой связал sizeof () информация. Мы не можем увеличить или постепенно уменьшить указатель. Мы не можем разыменовать для доступа к данным, хранившим в 0xffff0000. Мы можем только использовать значение как необработанный адрес памяти.
Если мы хотим использовать данные, хранившие в (пусто*) 0xffff0000, мы сначала должны бросить их к соответствующему типу.
Тем не менее (пусто *) все еще довольно полезно как средство передачи адресов к произвольным структурам данных вокруг. Например, memset (). Не имеет значения, являюсь ли я zero'ing TM структуры или структура sockaddr. Нам просто нужен указатель на структуру и ее размер.
(Это должно обойтись без помощи высказывания, но... Остерегайтесь использования memset для обнуления экземпляра класса и, при этом, перезаписывая виртуальную таблицу указателя.)
Пустой указатель не может указать участнику класса в C++.