Про потокобезопасность Hashtable
От: Eldar9x  
Дата: 11.11.11 10:02
Оценка:
MSDN

Объект Hashtable является безопасным для потоков при использовании несколькими потоками чтения и одним потоком записи. Этот объект безопасен для использования несколькими потоками, когда только один из потоков выполняет операции записи (обновления), что допускает свободное от блокировки чтение при условии, что потоки записи сериализованы в объект Hashtable. Чтобы была поддержка нескольких потоков записи, все операции с потоком Hashtable должны выполняться с использованием оболочки, возвращаемой методом Synchronizedпри условии, что нет ни одного потока, читающего объект Hashtable.


Объясните, пожалуйста, что это означает? :
при условии, что потоки записи сериализованы в объект Hashtable
int i;
i = (i++)+(i++);
cout << i;
Re: Про потокобезопасность Hashtable
От: perekrestov Украина  
Дата: 11.11.11 10:16
Оценка: 2 (1)
Здравствуйте, Eldar9x, Вы писали:



E>Объясните, пожалуйста, что это означает? :

E>
E>при условии, что потоки записи сериализованы в объект Hashtable
E>

Упорядочены, т.е. операции записи идут друг за другом, а не параллельно.
Re: Про потокобезопасность Hashtable
От: samius Япония http://sams-tricks.blogspot.com
Дата: 11.11.11 10:27
Оценка:
Здравствуйте, Eldar9x, Вы писали:

E>Объясните, пожалуйста, что это означает? :

E>
E>при условии, что потоки записи сериализованы в объект Hashtable
E>

which allows for lock-free reads provided that the writers are serialized to the Hashtable.

Значит что операции записи (не потоки) выполняются последовательно.
Re: Про потокобезопасность Hashtable
От: Eldar9x  
Дата: 11.11.11 10:45
Оценка:
Пасиб!
int i;
i = (i++)+(i++);
cout << i;
Re: Про потокобезопасность Hashtable
От: Eldar9x  
Дата: 11.11.11 11:17
Оценка:
Нет, как-то не складно получается...
То, что операции записи происходят последовательно, говорит вот это:

когда только один из потоков выполняет операции записи (обновления)


Тогда, получается масло масляное:


когда только один из потоков выполняет операции записи (обновления),
что допускает свободное от блокировки чтение при условии,
что потоки записи сериализованы в объект Hashtable.


так как подчеркнутые строчки — это, по сути, одно и то же... Не?
int i;
i = (i++)+(i++);
cout << i;
Re[2]: Про потокобезопасность Hashtable
От: Sshur Россия http://shurygin-sergey.livejournal.com
Дата: 11.11.11 11:46
Оценка:
Здравствуйте, Eldar9x, Вы писали:

E>

E>когда только один из потоков выполняет операции записи (обновления),
E>что допускает свободное от блокировки чтение при условии,
E>что потоки записи сериализованы в объект Hashtable.


E>так как подчеркнутые строчки — это, по сути, одно и то же... Не?


Чисто формально это не одно и то же, так как во втором случае потоков может быть много, но писать одновременно они не могут. В WinForms например что-то делать с UI контролом из другого потока в принципе нельзя, независимо от наличия других. А здесь можно.

На практике это конечно означает необходимость синхронизации, что сводит пользу от такой возможности на нет
Шурыгин Сергей

"Не следует преумножать сущности сверх необходимости" (с) Оккам
Re: Про потокобезопасность Hashtable
От: enCobalt  
Дата: 11.11.11 19:17
Оценка: 1 (1)
E>Объясните, пожалуйста, что это означает? :
E>
E>при условии, что потоки записи сериализованы в объект Hashtable
E>


Означает, что для того чтобы потокобезопасно надо

При записи в коллекцию делать:

Hashtable x = y.Synchronized()
и далее писать в копию x

При чтении получается что-то вроде dirty-read

Если надо коммитед рид, то делай и на записи и на чтении:

Lock(y.SyncRoot)
{
}
Хочу инвайт на хабру :)
Re[2]: Про потокобезопасность Hashtable
От: Eldar9x  
Дата: 12.11.11 12:40
Оценка:
Здравствуйте, enCobalt, Вы писали:



E>>Объясните, пожалуйста, что это означает? :

E>>
E>>при условии, что потоки записи сериализованы в объект Hashtable
E>>


C>Означает, что для того чтобы потокобезопасно надо


C>При записи в коллекцию делать:


C>Hashtable x = y.Synchronized()

C>и далее писать в копию x

C>При чтении получается что-то вроде dirty-read


C>Если надо коммитед рид, то делай и на записи и на чтении:


C>Lock(y.SyncRoot)

C>{
C>}

Да! Мне как раз и нужен коммитед рид.
Проблема вот в чем. Каждый объект в таблице имеет свой поток обновления (не выделенный, а из пула потоков).
То есть в каждый момент времени один и тот же элемент из таблицы меняется или читается только одним потоком.
Сделано это просто: для каждого объекта используется очередь Fiber из retlang. Так вот, если я при каждом обращении к хэштаблице
буду ее лочить, то вся эта параллельная обработка объектов в этой таблице идет коту под хвост.
Ладно в момент добавления/удаления элемента из таблицы, я еще могу залочить всю таблицу целиком — это происходит не так часто.
Но вот лочить таблицу при каждом обращении к одному из ее элементов, это губит всю задуманную схему. Как быть то?
int i;
i = (i++)+(i++);
cout << i;
Re[3]: Про потокобезопасность Hashtable
От: enCobalt  
Дата: 12.11.11 15:40
Оценка:
E>...Каждый объект в таблице имеет свой поток обновления (не выделенный, а из пула потоков).
E>То есть в каждый момент времени один и тот же элемент из таблицы меняется или читается только одним потоком.
...
E>Но вот лочить таблицу при каждом обращении к одному из ее элементов, это губит всю задуманную схему. Как быть то?

Лочишь не саму Hashtable, а её специальный объект Hashtable.SyncRoot
Если у тебя с потоками на обновление непосредственно внутри записей всё разрулилось,
то самая большая проблема это добавление/удаление записей в таблице.

Для удаления/добавления используй Monitor, можно сделать так

if (Monitor.TryEnter(MyTable.SyncRoot), 500)
{
    // можно добавлять удалять
    try
    {
      ...
    }
    finally
    {
        Monitor.Exit(MyTable.SyncRoot); // высвободить важно!!!
    }
}
else
{
    // Какой-то другой поток удаляет или добавляет новую запись, 
    // мы даже ждали 500 миллисекунд, но безуспешно, что-то не так
}



Это слегка похоже на джойн в поток, только с лучшим контролем, как успешная,
так и безуспешная попытка обрабатывается
.
Хочу инвайт на хабру :)
Re: [почти OFF] Hashtable
От: HowardLovekraft  
Дата: 12.11.11 19:45
Оценка:
Здравствуйте, Eldar9x, Вы писали:

E>skipped

Почему именно HashTable? Неужели проект на FW1.1?
Re[2]: [почти OFF] Hashtable
От: Eldar9x  
Дата: 14.11.11 11:06
Оценка:
Здравствуйте, HowardLovekraft, Вы писали:

HL>Здравствуйте, Eldar9x, Вы писали:


E>>skipped

HL>Почему именно HashTable? Неужели проект на FW1.1?

Нее. 3.5

Изучая монитор наткнулся на ReaderWriterLockSlim. Вроде бы, то что надо!

Еще подскажите, плиз, на такой вопрос:

Вот эти две функции одинаково потокобезопасно (на какой уровне нужно начинать блоктровку)?


class AnyObject
{
 public int i;

public void AnyMethod(int i)
{
this.i = i;
}
}

lock(locker)
{
   AnyObject.AnyMethod(5);
}


или же надо именно внутри метода использовать локер?

public void AnyMethod(int i)
{
lock(locker)
{
this.i = i;
}
}


Другими словами, насколько потокобезопасно вызывать из разных потоков один и тот же метод объекта, если внутри самого метода уже сделано все потокобезопасно?
int i;
i = (i++)+(i++);
cout << i;
Re[3]: [почти OFF] Hashtable
От: HowardLovekraft  
Дата: 14.11.11 17:42
Оценка:
Здравствуйте, Eldar9x, Вы писали:

E>Нее. 3.5


AFAIK, Rx под 3.5 содержат ConcurrentDictionary. Это лучше, чем заниматься велосипедостоением.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.