Ц #: Која је разлика између навоја и атома?


Одговор 1:

Средство без навоја не забрља се када му се приступа из више нити; атомски значи недељив, у том контексту еквивалентан непрекидном.

Да бисте имплементирали закључавање, имате два избора:

  1. Имајте хардверску подршку за атомске операције - посебна композитна упутства која се извршавају у целини, као што су Тест- и-. Буди паметна (и трпи последице) - Петерсон-ов алгоритам.

У вашем примеру у детаљима оба су несигурна; ако сам добро разумео, мислите овако:

јавна класа несигурно
{
    приватни објект закључавање = нови објект ();

    публиц инт Унсафе1 {гет; комплет; } = 0;

    привате инт _унсафе2 = 0;
    публиц инт Унсафе2
    {
        добити
        {
            закључавање (закључавање)
            {
                ретурн _унсафе2;
            }
        }

        комплет
        {
            закључавање (закључавање)
            {
                _унсафе2 = вредност;
            }
        }
    }
}

Тест цоде:

вар у = ново Унсафе ();

Параллел.Фор (0, 10000000, _ => {у.Унсафе1 ++;});
Параллел.Фор (0, 10000000, _ => {у.Унсафе2 ++;});

Цонсоле.ВритеЛине (стринг.Формат ("{0} - {1}", у.Унсафе1, у.Унсафе2));

Резултат (један од многих могућих):

4648265 - 4149827

За оба је више од половине ажурирања нестало.

Разлог је тај што ++ није атомски - у ствари су три одвојене операције:

  1. Добијте вредност.Додајте вредност 1.

То можемо поправити пружањем операције повећања која је атомска - постоје многи начини за то, али ево два:

јавна класа Сигурно
{
    приватни објект слоцк = нови објект ();

    публиц инт Сафе1 {гет; комплет; }
    јавна неваљана СафеИнцремент1 ()
    {
        закључавање (закључавање)
        {
            тхис.Сафе1 ++;
        }
    }

    привате инт _сафе2 = 0;
    публиц инт Сафе2
    {
        добити
        {
            ретурн _сафе2;
        }
        комплет
        {
            _сафе2 = вредност;
        }
    }
    јавна неважећа СафеИнцремент2 ()
    {
        Интерлоцкед.Инцремент (реф _сафе2);
    }
}

Тест цоде:

вар с = нови Сафе ();

Параллел.Фор (0, 10000000, _ => {с.СафеИнцремент1 ();});
Паралел.За (0, 10000000, _ => {с.СафеИнцремент2 ();});

Цонсоле.ВритеЛине (стринг.Формат ("{0} - {1}", с.Сафе1, с.Сафе2));

Резултати су тачни у оба случаја. Први само поставља браву око читаве композитне ++ операције, док други користи хардверску подршку за атомске операције.

Имајте у виду да је друга варијанта горе, са Интерлоцкед.Инцремент, много бржа, али је заправо нижег нивоа и ограничена на оно што може да ради ван кутије; међутим, операције у пакету Интерлоцкед могу се користити за имплементацију:

  1. Познате браве - назване „песимистичка истодобност“ јер претпостављају да ће се операција прекинути, па се не трудите започети док не стекну неки заједнички ресурс. „Код без закључавања“, а.к.а., „оптимистичка конкурентност“ - користећи нпр. Упоредите и замените, користите посебну вредност "канаринца" коју снимите на почетку, а затим проверите да се није променио под вама; Идеја је да ако се појави још једна нит, то ће убити канаринац, тако да знате да покушате поново с трансакцијом од почетка. Ово захтева и да ваш властити код буде атомски - не можете писати интермедијарне резултате у дељено стање, морате у потпуности успети или у потпуности успети (као да нисте извршили ниједну операцију).

Одговор 2:

Две потпуно различите ствари. Тхреад сафе означава функцију написану на такав начин да је може поновити у више наврата на више различитих нити, а да свака нит не омета рад другог нити (на пример, променом вредности ако променљива коју користи други нит)

Атомско значи (ако дођем тамо где идете) стварање једне инстанце објекта - па без обзира колико често се односи, увек видите ту једну инстанцу (из било које нити)


Одговор 3:

Атомске операције су начин да се постигне сигурност навоја било кориштењем некаквих брава попут Мутекес-а или Семапхорес-а које се користе атомским операцијама интерно или примјеном синхронизације без закључавања помоћу атомских и меморијских ограда.

Дакле, атомске операције на примитивним типовима података представљају алат за постизање сигурности нити, али не осигуравају сигурност нити аутоматски јер обично имате више операција које се ослањају једна на другу. Морате осигурати да се ове операције обављају без прекида, нпр. Коришћењем Мутекес-а.

Да, писање једног од ових типова атомских података у ц # је сигурно на нитима, али то не чини функцију коју користите у нитима сигурно. То само осигурава да се појединачно писање правилно изврши чак и ако му други низ приступа "истовремено". Ни мање ни друго, следеће читање из тренутне нити није осигурано да би се добила претходно написана вредност као што је другачија нит могла да јој је написана, само да је вредност прочитана.