1

Я пытаюсь реализовать функцию барьера, так что, когда поток вызывает waitBarrier(), он будет ждать, пока все остальные n нити вызовут функцию, после чего все будет продолжаться, т. Е. конструкция синхронизации.Назначение возвращаемого значения атомной функции

я следующий код:

int i = 0; // Shared variable. Initialized as 0 at the beginning. 

waitBarrier() { 

    // CAS = Compare-and-swap, the first argument holds "old_val" the second the new 
    i = CAS(i, i+1); 

    // Spin until all n threads (number of all threads known prior) have been "here" 
    while (i != n) {} 

} 

Если это получает доступ по n потоков будет эту функцию работать? Является ли назначение возвращаемого значения атомной функции атомом? Или могут возникнуть условия гонки?

+0

Если он работает, он будет работать плохо, (спинлока). –

+0

Хорошо, предполагая, что потоки ожидают короткого времени, он должен быть довольно эффективным. – spurra

+0

Чем больше потоков ожидает, тем меньше процессор и пропускная способность памяти останутся для остальных. –

ответ

2

Прежде всего, вам необходимо указать адрес регистра , значение которого вы сравниваете и обмениваете. Это может быть сделано с любым из следующих условий:

CAS(int* reg, int oldValue, int newValue) 

или

reg.CAS(int oldValue, int newValue) 

Если предположить, что линия сейчас будет:

i = i.CAS(i, i+1) 

себе две темы, призывающих waitBarrier() одновременно. Предполагая, что аргументы атомном функции оцениваются, не атомарно, т.е. оба потока будут на самом деле назвать i.CAS(0,1)

Кто атомный вызов выполняется первым будет успешно установить общую переменную я к 1. Поскольку CAS действительно всегда возвращает старый значение, имея присвоение i = OLD_VALUE_OF_i, вы фактически перезагружаете общую переменную до 0. Не только это, но представьте, что вы полностью опустите это задание и просто сделаете вызов CAS, тот, кто поток выполнит CAS второй, сравнит значение общей значение (которое теперь будет 1) с начальным значением i (во время оценки аргументов, равным 0), которое не будет выполнено, и поэтому общая переменная будет только увеличиваться один раз!

Принимая эти два аспекта во внимание, что ваш код должен выглядеть следующим образом:

int i = 0; 

waitBarrier() { 
    // Atomically increment the shared value i by 1 
    do { 
    int value = i; 
    } while (CAS(i, value, value + 1)); 

    // Wait until all threads have passed the barrier 
    while (i != n) {} 
}