Здравствуйте, Teolog, Вы писали:
T>Словарь хранит ссылки и позволяет их добавлять и удалять из разных потоков без самопальной внешней синхронизации. Это все для чего он предназначен, и все что делает. T>Синхронизация доступа в содержимому объекта по ссылке-отдельный веселый вопрос, который к словарю никакого отношения не имеет, и должен решаться вне зависимости от существования, не-существования, реализации и наличия документации на словарь, тем кто делал класс объекта.
Если словарь дает какие-то гарантии по поводу барьера памяти, то это один вопрос, и содержимое объекта можно использовать когда ты его получил из словаря.
Если он таких гарантий не дает, то получив ссылку на объект в другом треде, использовать эту ссылку ты не можешь. А это значит, что сохранять ссылки в словарь попросту нельзя. А это значит, что ссылки на объекты надо запретить в generic constraints класса. Доходит?
Здравствуйте, Codealot, Вы писали:
C>Если словарь дает какие-то гарантии по поводу барьера памяти, то это один вопрос, и содержимое объекта можно использовать когда ты его получил из словаря. C>Если он таких гарантий не дает, то получив ссылку на объект в другом треде, использовать эту ссылку ты не можешь. А это значит, что сохранять ссылки в словарь попросту нельзя. А это значит, что ссылки на объекты надо запретить в generic constraints класса. Доходит?
Понятно, о чем ты. Не понятно, причем тут ConcurrentDictionary и его документация, если ты опасаешься передать ссылку на объект в другой тред.
Здравствуйте, samius, Вы писали:
S>Понятно, о чем ты. Не понятно, причем тут ConcurrentDictionary и его документация, если ты опасаешься передать ссылку на объект в другой тред.
Плохо, что непонятно.
Тебе не приходило в голову, что ConcurrentDictionary именно для того и существует, чтобы использовать его из разных тредов? И если он позволяет использовать объекты — то либо он дает какие-то гарантии по поводу их извлечения, либо его разработчики крупно накосячили?
Здравствуйте, samius, Вы писали:
S>Реордерниг памяти — о чем ты?
Пусть изначально
global x := 0;
global y := 0;
В одном потоке выполняется
x := 1;
y := 2;
в другом потоке выполняется
local my_x := x;
local my_y := y;
Указанные инструкции выполняются на уровне машинного кода, т.е. компилятор ничего местами не поменял.
Реордеринг памяти это когда в my_x будет 0, а в my_y будет 2, хотя казалось бы логичны лишь варианты (0, 0) если до другого потока не дошли изменения; (1, 0) если дошло лишь первое изменение и (1, 2) если дошли оба изменения.
На x86 этой ситуации быть не может. На некоторых других архитектурах вроде ARM — может быть.
Здравствуйте, Codealot, Вы писали:
C>ConcurrentDictionary гарантирует безопасность объектов (если исходить из предположения, что они read-only), или нужны какие-то дополнительные движения с бубном? C>Документация чего-то не рассматривает этот вопрос
Я думаю, у тебя горе от ума. Используй и не парься. Ну или почитай его исходники и убедись, что там всё хорошо.
Здравствуйте, Codealot, Вы писали:
C>Здравствуйте, karbofos42, Вы писали:
K>>Я думал, что документацию для того и делают, чтобы людям не приходилось копаться в реализации и выяснять как что работает.
C>Там не ответов на вопросы, которые я задал.
All public and protected members of ConcurrentDictionary<TKey,TValue> are thread-safe and may be used concurrently from multiple threads. However, members accessed through one of the interfaces the ConcurrentDictionary<TKey,TValue> implements, including extension methods, are not guaranteed to be thread safe and may need to be synchronized by the caller.
K>All public and protected members of ConcurrentDictionary<TKey,TValue> are thread-safe and may be used concurrently from multiple threads. However, members accessed through one of the interfaces the ConcurrentDictionary<TKey,TValue> implements, including extension methods, are not guaranteed to be thread safe and may need to be synchronized by the caller.
Ты даже не понимаешь о чем идет речь, а туда же.
Имеется в виду потокобезопасность только самого объекта ConcurrentDictionary
Здравствуйте, Codealot, Вы писали:
C>Здравствуйте, samius, Вы писали:
S>>Понятно, о чем ты. Не понятно, причем тут ConcurrentDictionary и его документация, если ты опасаешься передать ссылку на объект в другой тред.
C>Плохо, что непонятно. C>Тебе не приходило в голову, что ConcurrentDictionary именно для того и существует, чтобы использовать его из разных тредов? И если он позволяет использовать объекты — то либо он дает какие-то гарантии по поводу их извлечения, либо его разработчики крупно накосячили?
Давай уберем ConcurrentDictionary и подумаем, можно ли использовать обеъкты из одного потока в другом и почему об этом не пишут на каждому углу, либо разработчики круто накосячили один ты в белом....
K>>All public and protected members of ConcurrentDictionary<TKey,TValue> are thread-safe and may be used concurrently from multiple threads. However, members accessed through one of the interfaces the ConcurrentDictionary<TKey,TValue> implements, including extension methods, are not guaranteed to be thread safe and may need to be synchronized by the caller.
C>Ты даже не понимаешь о чем идет речь, а туда же. C>Имеется в виду потокобезопасность только самого объекта ConcurrentDictionary
Ты хочешь потокобезопасность всего подряд только из-за того, что что-то там положили в потокобезопасную коллекцию.
Я тебе привёл официальную документацию, в которой написано потокобезопасность чего подразумевается в конкретном типе.
Нужна другая потокобезопасность — реализуй на здоровье, можешь на гитхаб выложить даже и кому надо — будет пользоваться.
Я тебе наверно сейчас жизнь испорчу, но они в Dictionary и без потоков накосячили и этим классом тоже пользоваться нельзя.
class MyKey
{
public int Value {get;set;}
public MyKey(int value) { Value = value;}
public override int GetHashCode() => Value;
public override bool Equals(object other) => (other as MyKey)?.Value == Value;
}
public class Program
{
public static void Main(string[] args)
{
var dict = new Dictionary<MyKey, string>();
var key = new MyKey(10);
dict.Add(key, "string1");
key.Value = 20;
dict.Add(key, "string2");
}
}
И ключ словаря менять разрешают и два элемента словаря под одним ключом записывать... О чём они там вообще думают?
Здравствуйте, samius, Вы писали:
S>Давай уберем ConcurrentDictionary и подумаем, можно ли использовать обеъкты из одного потока в другом и почему об этом не пишут на каждому углу, либо разработчики круто накосячили один ты в белом....
Нет, не давай уберем. Мы говорим о типе, созданном специально для многопоточности. И если простейший сценарий положить/извлечь объект опасен, то использовать ConcurrentDictionary с объектами попросту нельзя. Будешь спорить?
Здравствуйте, karbofos42, Вы писали:
K>Ты хочешь потокобезопасность всего подряд только из-за того, что что-то там положили в потокобезопасную коллекцию. K>Я тебе привёл официальную документацию, в которой написано потокобезопасность чего подразумевается в конкретном типе. K>Нужна другая потокобезопасность — реализуй на здоровье, можешь на гитхаб выложить даже и кому надо — будет пользоваться.
Я повторю еще раз, для самых быстрых.
Мы говорим о типе, созданном специально для многопоточности. И если в нем простейший сценарий положить/извлечь объект опасен, то использовать ConcurrentDictionary с объектами попросту нельзя. А это значит, что generic constraint типа должен в явном виде их запретить. Не доходит?
Здравствуйте, vsb, Вы писали:
vsb>Реордеринг памяти это когда в my_x будет 0, а в my_y будет 2, хотя казалось бы логичны лишь варианты (0, 0) если до другого потока не дошли изменения; (1, 0) если дошло лишь первое изменение и (1, 2) если дошли оба изменения.
Понятно, это на уровне конкретного CPU, и в модели памяти дотнета (и джавы тоже) такого нет.
vsb>На x86 этой ситуации быть не может. На некоторых других архитектурах вроде ARM — может быть.
Такое — верятно. Но речь ведь в данном треде немного о другом, почему можно взять из ConcurrentDictionary ссылку на объект и ей пользоваться... Но ответ как раз в модели памяти дотнета, а не в библиотечном классе ConcurrentDictionary или его документации.
Здравствуйте, Codealot, Вы писали:
C>Здравствуйте, samius, Вы писали:
S>>Давай уберем ConcurrentDictionary и подумаем, можно ли использовать обеъкты из одного потока в другом и почему об этом не пишут на каждому углу, либо разработчики круто накосячили один ты в белом....
C>Нет, не давай уберем. Мы говорим о типе, созданном специально для многопоточности. И если простейший сценарий положить/извлечь объект опасен, то использовать ConcurrentDictionary с объектами попросту нельзя. Будешь спорить?
Лет несколько назад — поспорил бы.
Здравствуйте, Codealot, Вы писали:
C>Здравствуйте, karbofos42, Вы писали:
K>>Ты хочешь потокобезопасность всего подряд только из-за того, что что-то там положили в потокобезопасную коллекцию. K>>Я тебе привёл официальную документацию, в которой написано потокобезопасность чего подразумевается в конкретном типе. K>>Нужна другая потокобезопасность — реализуй на здоровье, можешь на гитхаб выложить даже и кому надо — будет пользоваться.
C>Я повторю еще раз, для самых быстрых.
C>Мы говорим о типе, созданном специально для многопоточности. И если в нем простейший сценарий положить/извлечь объект опасен, то использовать ConcurrentDictionary с объектами попросту нельзя. А это значит, что generic constraint типа должен в явном виде их запретить. Не доходит?
Я там дополнил своё сообщение примером с "обычным" словарём.
Создали специальный тип для хранения значений по уникальным ключам, но и тут накосячили.
Ничем нельзя пользоваться выходит, нужно всё своё писать правильное.
K>>All public and protected members of ConcurrentDictionary<TKey,TValue> are thread-safe and may be used concurrently from multiple threads. However, members accessed through one of the interfaces the ConcurrentDictionary<TKey,TValue> implements, including extension methods, are not guaranteed to be thread safe and may need to be synchronized by the caller.
C>Ты даже не понимаешь о чем идет речь, а туда же. C>Имеется в виду потокобезопасность только самого объекта ConcurrentDictionary
А что по твоему еще должно быть?
За потокобезопасность объекты ты уже сам должен позаботиться.
Или ты хочешь, что бы внутри методов класса автоматически генерировалиь потокобезопасные конструкции изменения полей, volatile
Ну и стоит почитать Доступ к локальной переменной из разных потоков