Я новичок в многопоточном программировании, и я пытался закодировать Алгоритм блокировки хлебобулочных изделий в C.
Вот код:
int number[N]; // N is the number of threads
int choosing[N];
void lock(int id) {
choosing[id] = 1;
number[id] = max(number, N) + 1;
choosing[id] = 0;
for (int j = 0; j < N; j++)
{
if (j == id)
continue;
while (1)
if (choosing[j] == 0)
break;
while (1)
{
if (number[j] == 0)
break;
if (number[j] > number[id]
|| (number[j] == number[id] && j > id))
break;
}
}
}
void unlock(int id) {
number[id] = 0;
}
Затем я запускаю следующий пример. Я запускаю 100 потоков, и каждый поток запускает следующий код:
for (i = 0; i < 10; ++i) {
lock(id);
counter++;
unlock(id);
}
После того, как все потоки были выполнены, результатом общего counter
будет 10 * 100 = 1000
, который является ожидаемым значением. Я выполнил свою программу несколько раз, и результат всегда был 1000
. Таким образом, кажется, что реализация блокировки является правильной. Это казалось странным из-за предыдущего вопроса , который у меня был, потому что я не использовал никаких барьеров / ограждений памяти. Мне просто повезло ?
Тогда я хотел создать многопоточную программу, которая будет использовать много разных блокировок. Итак, я создал это (полный код можно найти здесь ):
typedef struct {
int number[N];
int choosing[N];
} LOCK;
и код меняется на:
void lock(LOCK l, int id)
{
l.choosing[id] = 1;
l.number[id] = max(l.number, N) + 1;
l.choosing[id] = 0;
...
Теперь при выполнении моей программы иногда я получаю 997
, иногда 998
, иногда 1000
. Так что алгоритм блокировки не верен.
Что я делаю не так? Что я могу сделать, чтобы это исправить?
Возможно, это проблема сейчас, когда я читаю массивы number
и choosing
из struct
а это не атомно что ли?
Должен ли я использовать ограждения памяти и, если да, то в каких точках (я пытался использовать asm("mfence")
в разных точках моего кода, но это не помогло)?