CSHARP_GEPARD Telegram 104
ConcurrentDictionary #собес #память

Коллеги, задачка. Прямо с собеса, с пылу-с-жару. Сколько раз значение будет выведено в консоль?


const string Key = "SomeKey";
var topLevel = new ConcurrentDictionary<string, string>();

for (var i = 1; i < 100; i++) {
var thread = new Thread(Add);
thread.Start(topLevel);
}

static void Add(object? val) {
var dict = (ConcurrentDictionary<string, string>)val!;
dict.GetOrAdd(Key, x => {
lock (Lock.Obj)
{
if (dict.TryGetValue(Key, out var value)) return value;
var res = Guid.NewGuid().ToString();
Console.WriteLine(res);
return res;
}
});
}


Усложняем:
1. Теперь заменим тип значения у ConcurrentDictionary на Guid. Естественно строку var res = Guid.NewGuid().ToString(); нужно исправить как var res = Guid.NewGuid().
2. А теперь изменим тип значения на int.

Как же так? Надо пояснить в чём, собственно, дело. Можно скопировать и воспроизвести у себя. И я настоятельно (!) рекомендую это сделать.

---

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

А другой стороны, суть происходящего в сложном сценарии не так проста, но всё ещё, кстати, логична.

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

Причём скорость зависит (c) от всего сразу: размера данных, количества процессоров, разрядности процессора и скорости памяти. Например, размер int это 4, а string - 8. И, если повезёт, это, в свою очередь, равно sizeof(IntPtr) или nint (в зависимости от разрядности процессора). Если разрядность позволяет записать данные в память за одну операцию, то это дает другим потокам (ядрам) больше времени посоревноваться на скорость. Если поток всего один - то конкуренции нет.

Мораль всего этого такова: осторожнее на собеседованиях. Нет, мораль другая - если мы пишем асинхронный код, то было бы неплохо протестировать наши результаты не только у себя, но, также, на целевой машине и у того парня. Возможно, наш гениальный код будет работать тут, но не там, а вот там - он вообще всё сломает.
🔥6👍21👏1



tgoop.com/csharp_gepard/104
Create:
Last Update:

ConcurrentDictionary #собес #память

Коллеги, задачка. Прямо с собеса, с пылу-с-жару. Сколько раз значение будет выведено в консоль?


const string Key = "SomeKey";
var topLevel = new ConcurrentDictionary<string, string>();

for (var i = 1; i < 100; i++) {
var thread = new Thread(Add);
thread.Start(topLevel);
}

static void Add(object? val) {
var dict = (ConcurrentDictionary<string, string>)val!;
dict.GetOrAdd(Key, x => {
lock (Lock.Obj)
{
if (dict.TryGetValue(Key, out var value)) return value;
var res = Guid.NewGuid().ToString();
Console.WriteLine(res);
return res;
}
});
}


Усложняем:
1. Теперь заменим тип значения у ConcurrentDictionary на Guid. Естественно строку var res = Guid.NewGuid().ToString(); нужно исправить как var res = Guid.NewGuid().
2. А теперь изменим тип значения на int.

Как же так? Надо пояснить в чём, собственно, дело. Можно скопировать и воспроизвести у себя. И я настоятельно (!) рекомендую это сделать.

---

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

А другой стороны, суть происходящего в сложном сценарии не так проста, но всё ещё, кстати, логична.

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

Причём скорость зависит (c) от всего сразу: размера данных, количества процессоров, разрядности процессора и скорости памяти. Например, размер int это 4, а string - 8. И, если повезёт, это, в свою очередь, равно sizeof(IntPtr) или nint (в зависимости от разрядности процессора). Если разрядность позволяет записать данные в память за одну операцию, то это дает другим потокам (ядрам) больше времени посоревноваться на скорость. Если поток всего один - то конкуренции нет.

Мораль всего этого такова: осторожнее на собеседованиях. Нет, мораль другая - если мы пишем асинхронный код, то было бы неплохо протестировать наши результаты не только у себя, но, также, на целевой машине и у того парня. Возможно, наш гениальный код будет работать тут, но не там, а вот там - он вообще всё сломает.

BY C# Heppard


Share with your friend now:
tgoop.com/csharp_gepard/104

View MORE
Open in Telegram


Telegram News

Date: |

As the broader market downturn continues, yelling online has become the crypto trader’s latest coping mechanism after the rise of Goblintown Ethereum NFTs at the end of May and beginning of June, where holders made incoherent groaning sounds and role-played as urine-loving goblin creatures in late-night Twitter Spaces. The best encrypted messaging apps Ng was convicted in April for conspiracy to incite a riot, public nuisance, arson, criminal damage, manufacturing of explosives, administering poison and wounding with intent to do grievous bodily harm between October 2019 and June 2020. A new window will come up. Enter your channel name and bio. (See the character limits above.) Click “Create.” Ng, who had pleaded not guilty to all charges, had been detained for more than 20 months. His channel was said to have contained around 120 messages and photos that incited others to vandalise pro-government shops and commit criminal damage targeting police stations.
from us


Telegram C# Heppard
FROM American