У автора есть грубая ошибка!
в main создан указатель
>>DATA *arg;позднее он в цикле инициализируется объектом (тоже в main)
>> arg = new DATA;
но удаляется объект почемуто из функций потоков
>> delete a; // удаляем свои данные
причем удаление происходит После разблокирования мутекса!
Так делать очень опасно!
можете легко прибить чужой объект или вычитать чужие данные (чтение тоже выполняется вне лока мутекса почемуто)
Безопасные варианты:
1) создать массив указателей
DATA *arg[SIZE_I][SIZE_J]
и отдавать каждому потоку указатель на индивидуальный кусок памяти.
2)выполнять все операции с общей памятью только при заблокированном мутексе (тоесть в потоках чтение, модификация и освобождение общей памяти должно быть внутри общего pthread_mutex_lock(&lock)).
3) удалять объекты только в том потоке который их создал.
Код статьи в качестве примера использовать не рекомендуется ибо в нем автор наступил на те грабли от которых по идее должен уберечь читателей.