Re[7]: pthread mutex concurrent threads
От: green.nsk  
Дата: 25.10.07 12:49
Оценка:
Здравствуйте, ДимДимыч, Вы писали:

ДД>От ситуации зависит. В случае как у топикстартера, когда есть один непрерывно работающий поток, и второй — периодически модифицирующий данные, я бы использовал условную переменную для сигнализации.


Я согласен, что мой пример "синтетический" и врядли имеет отношение к жизни, я просто проиллюстрировал проблему. В реальной программе всё не совсем так, но суть остаётся такая же: потоки, у которых заведомо одинаковый приоритет, могут заблокировать друг друга.
Re[9]: pthread mutex concurrent threads
От: Pzz Россия https://github.com/alexpevzner
Дата: 25.10.07 12:53
Оценка:
Здравствуйте, green.nsk, Вы писали:

Pzz>>В смысле, явно переключиться туда-обратно? А почему не пару семафоров?


GN>потому что с семафорами всё также по-уродски работает


Я имел ввиду как-то так:

sem_t *sem1, *sem2;

thread1()
{
    for(;;)
    {
        do_work_1();
        sem_post( sem1 );
        sem_wait( sem2 );
    }
}

thread2()
{
    for(;;)
    {
        do_work_2();
        sem_post( sem2 );
        sem_wait( sem1 );
    }
}
Re[8]: pthread mutex concurrent threads
От: ДимДимыч Украина http://klug.org.ua
Дата: 25.10.07 12:57
Оценка:
Здравствуйте, green.nsk, Вы писали:

GN>Я согласен, что мой пример "синтетический" и врядли имеет отношение к жизни, я просто проиллюстрировал проблему.


Единственная задача мютекса — предотвратить противоречивое состояние данных. Для управления планированием должны использоваться иные механизмы.

GN>В реальной программе всё не совсем так, но суть остаётся такая же: потоки, у которых заведомо одинаковый приоритет, могут заблокировать друг друга.


В данном случае они друг друга не блокируют, один ведь продолжает работать. Заблокироватся могут и с разными приоритетами, если например не соблюдают порядок захвата ресурсов.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Re[6]: pthread mutex concurrent threads
От: mr_jek  
Дата: 25.10.07 12:59
Оценка:
Здравствуйте, green.nsk, Вы писали:

GN> А тут дедлок какой-то получается.


ну что-то же работает значит не deadlock

GN>Точно также не согласен с тем, что плохой дизайн — держать мутекс захваченным (почти) всё время. Могу нафантазировать кучу примеров, когда это вполне логично и эффективно.


давайте хотя бы один пример
Re[10]: pthread mutex concurrent threads
От: ДимДимыч Украина http://klug.org.ua
Дата: 25.10.07 13:00
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>
Pzz>sem_t *sem1, *sem2;


А если 3 или больше нитей?
Вообще, это решается одним мютексом (или семафором — не суть) и одной условной переменной.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Re[4]: pthread mutex concurrent threads
От: mr_jek  
Дата: 25.10.07 13:09
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>>>Явная бага в реализации мутексов.


А>>Почему бага?


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


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


а вот это в POSIX есть:
When threads executing with the scheduling policy SCHED_FIFO, SCHED_RR, or
SCHED_SPORADIC are waiting on a mutex, they shall acquire the mutex in priority order when the mutex is
unlocked.

и я думаю реализовано, и если поднять приоритет одному из них, то именно он будет держать mutex
Re: pthread mutex concurrent threads
От: dev1024  
Дата: 25.10.07 16:00
Оценка: 3 (1)
Уже обсуждалось:
http://www.linux.org.ru/view-message.jsp?msgid=2149003
Re[2]: pthread mutex concurrent threads
От: ДимДимыч Украина http://klug.org.ua
Дата: 25.10.07 19:41
Оценка:
Здравствуйте, dev1024, Вы писали:

D>Уже обсуждалось:

D>http://www.linux.org.ru/view-message.jsp?msgid=2149003

Забавно все-таки, как детерминировано развивается дискуссия даже при разной аудитории
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Re: pthread mutex concurrent threads
От: McQwerty Россия  
Дата: 26.10.07 15:05
Оценка:
Под MS Windows всё нормально
Стало быть, такое поведение планировщика может не всех устраивать. Возможно, поможет вызов pthread_attr_setschedpolicy с другой политикой.

Код, вроде, эквивалентный:
#include <windows.h>
#include <stdio.h>
#include <signal.h>

HANDLE mutex = INVALID_HANDLE_VALUE;

volatile int continue_loop = 1;

DWORD WINAPI thread (LPVOID p)
{
    while (continue_loop)
    {
        WaitForSingleObject (mutex, INFINITE);
        printf ((char*) p);
        Sleep (2000);
        ReleaseMutex (mutex);
    }
    
    return 0;
} // thread

void signal_handler (int /* signal */)
{
    continue_loop = 0;
} // signal_handler

int main (int, char**)
{
    printf ("start\n");

    mutex = CreateMutex (NULL, FALSE, NULL);
    HANDLE threads [2] = { 0 };
    DWORD thread_id = 0;
    threads [0] = CreateThread (NULL, 0, thread, "thread 1\n", NULL, &thread_id);
    threads [1] = CreateThread (NULL, 0, thread, "thread 2\n", NULL, &thread_id);

    void (* save_SIGINT) (int) = signal (SIGINT, signal_handler);

    WaitForMultipleObjects (2, threads, TRUE, INFINITE);

    signal (SIGINT, save_SIGINT);

    CloseHandle (threads [1]);
    CloseHandle (threads [0]);
    CloseHandle (mutex);

    printf ("done\n");

    return 0;
} // main


C:\Projects\tst037\Debug>ver

Microsoft Windows XP [Version 5.1.2600]

C:\Projects\tst037\Debug>tst037
start
thread 1
thread 2
thread 1
thread 2
thread 1
thread 2
thread 1
thread 2
thread 1
thread 2
done

Re[4]: pthread mutex concurrent threads
От: Аноним  
Дата: 28.10.07 14:22
Оценка:
Здравствуйте, green.nsk, Вы писали:

А>>кстати а почему просто не повысить приоритет потоку который никак не может захватить mutex,

А>>в данном примере это не понятно какой (у меня управление получал и первый и второй),
А>>но судя по описанию есть какой-то один который так и не может захватить мьютекс.

GN>А позвольте поинтересоваться Вашей конфигурацией

GN>У меня на ядрах 2.6 управление получает только тот поток, который первым захватил мутекс. На ядрах 2.4 всё работает, как Вы говорите

а ядро 2.6.23 вы пробовали? у меня на нем потоки работали попеременно
Re[5]: pthread mutex concurrent threads
От: Pzz Россия https://github.com/alexpevzner
Дата: 28.10.07 17:10
Оценка:
Здравствуйте, mr_jek, Вы писали:

_>а вот это в POSIX есть:

_> When threads executing with the scheduling policy SCHED_FIFO, SCHED_RR, or
_> SCHED_SPORADIC are waiting on a mutex, they shall acquire the mutex in priority order when the mutex is
_> unlocked.

_>и я думаю реализовано, и если поднять приоритет одному из них, то именно он будет держать mutex


Я не совсем про то. Если поток с низким приоритетом уже держит мутекс, и он (мутекс) понадобился потоку с высоким приоритетом, то может получиться так, что поток в высоким приоритетом ждет мутекса, а поток с низким приоритетом не получает управления (из-за своего низкого приоритета), и поэтому мутекс не отдает. Это называется инверсия приоритета.

Классическое решение заключается в том, что если поток с высоким приоритетом заблокировался на мутексе, то потоку, который мутекс в данный момент держит, временно повышают приоритет — чтобы он побыстрее кончил свои делишьки и убрался с дороги.
Re[7]: pthread mutex concurrent threads
От: green.nsk  
Дата: 29.10.07 04:56
Оценка:
Здравствуйте, mr_jek, Вы писали:

GN>>Точно также не согласен с тем, что плохой дизайн — держать мутекс захваченным (почти) всё время. Могу нафантазировать кучу примеров, когда это вполне логично и эффективно.


_>давайте хотя бы один пример


Задержался с ответом, простите. Напишу псевдокодом, надеюсь, смысл донесу:
array<SOCKET> clientsArray; // сокеты, через которые происходит общение с клиентами
MUTEX clientsArrayMutex; // мутекс, который регулирует доступ к этому массиву

// Эти два сокета связываются друг с другом на стадии инициализации
SOCKET workerSender; // сокет, через который мы отправляем команды worker'у
SOCKET workerListener; // сокет, через который worker получает команды

SEMAPHORE serverPause; // семафор, на котором worker висит, когда мы хотим его "приостановить"

void worker()
{
   fd_set cacheFdset;
   bool reloadClients = true;
   while(true)
   {
      fd_set selectTarget;
      OwnMutex(clientsArrayMutex); // захват
      if (reloadClients)
      {
          FD_ZERO(&cacheFdset);
          FD_SET(workerListener, &cacheFdset);
          foreach(client in clientsArray) FD_SET(client, &cacheFdset);
          reloadClients = false;
      }

      selectTarget = cacheFdset;
      int selectResult = select(selectTarget, infinite);

      if (selectResult < 0) break;

      foreach(client in clientsArray)
      {
         if (FD_ISSET(client, &selectTarget))
              HandleClientActivity(client);
      }

      ReleaseMutex(clientsArrayMutex); // освобождение

      if (FD_ISSET(workerListener, &selectTarget))
           ProcessWorkerCommand();
    } // while
}

// ну и например

void AddClient(SOCKET newClient)
{
   OwnSemaphore(serverPause);
   SendCommand("reload clients");
   OwnMutex(clientsArrayMutex);

   clientsArray.Add(newCLient);

   ReleaseMutex(clientsArrayMutex);
   ReleaseSemaphore(serverPause);
}


На мой взгляд, в этом случае достаточно разумно держать мутекс "почти всё время". Конечно, здесь, в отличие от примера в первом посте, ничего плохого не произойдёт, если сервер честно висит на serverPause внутри ProcessWorkerCommand(). С указанным в первом посте примером имеет мало общего и приведён для того, чтобы подтвердить тезис о том, что "держать мутекс (почти) всё время — необязательно признак плохого дизайна".

Можно, конечно, обсуждать применение именно мутексов/семафоров в данном случае, но нафантазировать другие (более-менее классические) примитивы синхронизации, которые могут что-то сильно упростить в этом случае, у меня не получается (уж не говоря про то, что, например, в winapi набор примитивов синхронизации достаточно ограничен, а целесообразность конструирования более сложных из доступных — сомнительна).
Re[5]: pthread mutex concurrent threads
От: green.nsk  
Дата: 29.10.07 05:24
Оценка:
Здравствуйте, Аноним, Вы писали:

А>а ядро 2.6.23 вы пробовали? у меня на нем потоки работали попеременно


Нет, не пробовал. К сожалению, под рукой ничего свежее 2.6.18 нет, а пересобирать ради этой фигни лень Если найду — может попробую, а так — очевидно, что исправлять в своём коде придётся. Просто порадуюсь, что в ядре всё же происходят изменения к лучшему.
Re[6]: pthread mutex concurrent threads
От: ДимДимыч Украина http://klug.org.ua
Дата: 29.10.07 09:02
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Если поток с низким приоритетом уже держит мутекс, и он (мутекс) понадобился потоку с высоким приоритетом, то может получиться так, что поток в высоким приоритетом ждет мутекса, а поток с низким приоритетом не получает управления (из-за своего низкого приоритета), и поэтому мутекс не отдает. Это называется инверсия приоритета.


Но если не ошибаюсь, такое может возникнуть только тогда, когда еще как минимум один поток с высоким приоритетом?
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Re[7]: pthread mutex concurrent threads
От: Pzz Россия https://github.com/alexpevzner
Дата: 29.10.07 11:43
Оценка:
Здравствуйте, ДимДимыч, Вы писали:

ДД>Но если не ошибаюсь, такое может возникнуть только тогда, когда еще как минимум один поток с высоким приоритетом?


Ну естественно.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.