Синхронизация на доступ при добавлении объекта
От: Аноним  
Дата: 11.03.10 09:30
Оценка:
Добрый день,
На собеседовании задали вопрос:

есть класс:

    public class SimpleCub 
    {
        public int X
        {
            get;
            private set;
        }

        public int Y
        {
            get;
            private set;
        }

        public int Z
        {
            get;
            private set;
        }

        public SimpleCub(int x, int y, int z)
        {
            X = x;
            Y = y;
            Z = z;
        }

        #region Equals_GetHashCode Members

        public override bool Equals(Object obj)
        {
            if (obj == null || GetType() != obj.GetType())
                return false;
            SimpleCub simpleCube = (SimpleCub)obj;
            return ((simpleCube.X == X) && (simpleCube.Y == Y) && (simpleCube.Z == Z));
        }

        public override int GetHashCode()
        {
            Func<byte[], int> calcHash = (arr) =>
                                             {
                                                 using (RIPEMD160Managed myRIPEMD160 = new RIPEMD160Managed())
                                                 {
                                                     return BitConverter.ToInt32(myRIPEMD160.ComputeHash(arr), 0);
                                                 }
                                             };
            
            List<byte> listBytes = new List<byte>(BitConverter.GetBytes(X));
            listBytes.AddRange(BitConverter.GetBytes(Y));
            listBytes.AddRange(BitConverter.GetBytes(Z));
            return calcHash(listBytes.ToArray());
        }

        #endregion
    }


по определенным правилам создаются допустим 10 экземпляров данного типа и добавляются в List<SimpleCub> list1
эти же созданные экземпляры добавляются в List<SimpleCub> list2
создается дочерний поток thread1 и передается в него list1
создается дочерний поток thread2 и передается в него list2

в дочерних потоках создается (в 1-м):
dic1 = new Dictionary<SimpleCub, object>();

(во 2-м):
dic2 = new Dictionary<SimpleCub, object>();

и соответсвенно добавляются элементы SimpleCub (в качестве ключа) в dic1 из list1
добавляются элементы SimpleCub (в качестве ключа) в dic2 из list2

далее в каждом из дочерних потоках создаются новые SimpleCub и добавляются в dic1 или dic2 в качестве ключа.

Вопрос:
Нужна ли блокировка(синхронизация) при добавлении элементов в dic1 и dic2 ?
Re: Синхронизация на доступ при добавлении объекта
От: Мишень-сан  
Дата: 11.03.10 10:10
Оценка: +2
Здравствуйте, Аноним, Вы писали:

  Скрытый текст
А>Добрый день,
А>На собеседовании задали вопрос:

А>есть класс:


А>
А>    public class SimpleCub 
А>    {
А>        public int X
А>        {
А>            get;
А>            private set;
А>        }

А>        public int Y
А>        {
А>            get;
А>            private set;
А>        }

А>        public int Z
А>        {
А>            get;
А>            private set;
А>        }

А>        public SimpleCub(int x, int y, int z)
А>        {
А>            X = x;
А>            Y = y;
А>            Z = z;
А>        }

А>        #region Equals_GetHashCode Members

А>        public override bool Equals(Object obj)
А>        {
А>            if (obj == null || GetType() != obj.GetType())
А>                return false;
А>            SimpleCub simpleCube = (SimpleCub)obj;
А>            return ((simpleCube.X == X) && (simpleCube.Y == Y) && (simpleCube.Z == Z));
А>        }

А>        public override int GetHashCode()
А>        {
А>            Func<byte[], int> calcHash = (arr) =>
А>                                             {
А>                                                 using (RIPEMD160Managed myRIPEMD160 = new RIPEMD160Managed())
А>                                                 {
А>                                                     return BitConverter.ToInt32(myRIPEMD160.ComputeHash(arr), 0);
А>                                                 }
А>                                             };
            
А>            List<byte> listBytes = new List<byte>(BitConverter.GetBytes(X));
А>            listBytes.AddRange(BitConverter.GetBytes(Y));
А>            listBytes.AddRange(BitConverter.GetBytes(Z));
А>            return calcHash(listBytes.ToArray());
А>        }

А>        #endregion
А>    }
А>


А>по определенным правилам создаются допустим 10 экземпляров данного типа и добавляются в List<SimpleCub> list1

А>эти же созданные экземпляры добавляются в List<SimpleCub> list2
А>создается дочерний поток thread1 и передается в него list1
А>создается дочерний поток thread2 и передается в него list2

А>в дочерних потоках создается (в 1-м):

А>dic1 = new Dictionary<SimpleCub, object>();

А>(во 2-м):

А>dic2 = new Dictionary<SimpleCub, object>();

А>и соответсвенно добавляются элементы SimpleCub (в качестве ключа) в dic1 из list1

А>добавляются элементы SimpleCub (в качестве ключа) в dic2 из list2

А>далее в каждом из дочерних потоках создаются новые SimpleCub и добавляются в dic1 или dic2 в качестве ключа.


А>Вопрос:

А>Нужна ли блокировка(синхронизация) при добавлении элементов в dic1 и dic2 ?

Только если Вы пытаетесь работать с любым из словарей из более чем одного потока
Re: Синхронизация на доступ при добавлении объекта
От: samius Япония http://sams-tricks.blogspot.com
Дата: 11.03.10 10:35
Оценка: +2 :)
Здравствуйте, Аноним, Вы писали:

А>Добрый день,

А>На собеседовании задали вопрос:

А>
А>        public override int GetHashCode()
А>        {
А>            Func<byte[], int> calcHash = (arr) =>
А>                                             {
А>                                                 using (RIPEMD160Managed myRIPEMD160 = new RIPEMD160Managed())
А>                                                 {
А>                                                     return BitConverter.ToInt32(myRIPEMD160.ComputeHash(arr), 0);
А>                                                 }
А>                                             };
            
А>            List<byte> listBytes = new List<byte>(BitConverter.GetBytes(X));
А>            listBytes.AddRange(BitConverter.GetBytes(Y));
А>            listBytes.AddRange(BitConverter.GetBytes(Z));
А>            return calcHash(listBytes.ToArray());
А>        }
А>


Я фигею с такого GetHashCode()!!!
Получить 160-битный хэшкод по 96и битам и обрезать его в 32
Re[2]: Синхронизация на доступ при добавлении объекта
От: Аноним  
Дата: 11.03.10 11:21
Оценка:
Здравствуйте, Мишень-сан, Вы писали:


МС>Только если Вы пытаетесь работать с любым из словарей из более чем одного потока


в dic1 добавляются элементы только в потоке1, а в dic2 добавляются элементы только в потоке2

таким образом Ваш ответ блокировка(синхронизация) не нужна когда требуется добавлять новые SimpleCub в словари
??
Re[2]: Синхронизация на доступ при добавлении объекта
От: Аноним  
Дата: 11.03.10 11:27
Оценка:
Здравствуйте, samius, Вы писали:

S>Я фигею с такого GetHashCode()!!!

S>Получить 160-битный хэшкод по 96и битам и обрезать его в 32

за отсутствием другого варианта используем RIPEMD160Managed

вариант X ^ Y ^ Z не подходит....
Re[3]: Синхронизация на доступ при добавлении объекта
От: samius Япония http://sams-tricks.blogspot.com
Дата: 11.03.10 12:01
Оценка:
Здравствуйте, Аноним, Вы писали:

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


S>>Я фигею с такого GetHashCode()!!!

S>>Получить 160-битный хэшкод по 96и битам и обрезать его в 32

А>за отсутствием другого варианта используем RIPEMD160Managed

Сомневаюсь что нет другого варианта

А>вариант X ^ Y ^ Z не подходит....

Надо просто посмотреть чем не подходит. Если тем что дает один код для координат (1, 0, 0) и (0, 1, 0), то это решается по-другому. Например, сдвигом.
Re[3]: Синхронизация на доступ при добавлении объекта
От: Jolly Roger  
Дата: 11.03.10 12:10
Оценка:
Здравствуйте, Аноним, Вы писали:

А>в dic1 добавляются элементы только в потоке1, а в dic2 добавляются элементы только в потоке2


А>таким образом Ваш ответ блокировка(синхронизация) не нужна когда требуется добавлять новые SimpleCub в словари

А>??

Ну а что именно Вы собираетесь лочить? У Вас, как я понял, есть готовый класс и не менее готовый словарь. Покажите псевдокодом, в каком именно месте Вы собираетесь ставить влокировку и поясните, от каких ситуаций она, по Вашему мнению, должна Вас эащитить.
"Нормальные герои всегда идут в обход!"
Re[4]: Синхронизация на доступ при добавлении объекта
От: Аноним  
Дата: 11.03.10 12:19
Оценка:
Здравствуйте, samius, Вы писали:

А>>за отсутствием другого варианта используем RIPEMD160Managed

S>Сомневаюсь что нет другого варианта

А>>вариант X ^ Y ^ Z не подходит....

S>Надо просто посмотреть чем не подходит. Если тем что дает один код для координат (1, 0, 0) и (0, 1, 0), то это решается по-другому. Например, сдвигом.
Да, потому что одинаковый хэш для (1, 0, 0) и (0, 1, 0).
RIPEMD160Managed дает приемлемую производительность при подсчете хэша на 12 байт.
Хотя попробую покопать в строну сдвига...
Re[4]: Синхронизация на доступ при добавлении объекта
От: Аноним  
Дата: 11.03.10 12:34
Оценка:
Здравствуйте, samius, Вы писали:

А>>вариант X ^ Y ^ Z не подходит....

S>Надо просто посмотреть чем не подходит. Если тем что дает один код для координат (1, 0, 0) и (0, 1, 0), то это решается по-другому. Например, сдвигом.

придумал вот такой сдвиг:
        int t = X << 8;
        t ^= Y;
        t <<= 8;
        t ^= Z;
        t <<= 8;

в t после сдвига в последней строчке содержится хэш.
Re[5]: Синхронизация на доступ при добавлении объекта
От: samius Япония http://sams-tricks.blogspot.com
Дата: 11.03.10 13:01
Оценка: 1 (1)
Здравствуйте, Аноним, Вы писали:

А>придумал вот такой сдвиг:

А>
А>        int t = X << 8;
А>        t ^= Y;
А>        t <<= 8;
А>        t ^= Z;
А>        t <<= 8;
А>

А>в t после сдвига в последней строчке содержится хэш.

Отлично. Только лучше int заменить на long и потом взять t.GetHashCode(). Тогда старшие байты координат не потеряются.
Re[4]: Синхронизация на доступ при добавлении объекта
От: Аноним  
Дата: 11.03.10 13:14
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

JR>Ну а что именно Вы собираетесь лочить? У Вас, как я понял, есть готовый класс и не менее готовый словарь. Покажите псевдокодом, в каком именно месте Вы собираетесь ставить влокировку и поясните, от каких ситуаций она, по Вашему мнению, должна Вас эащитить.


Хоть "старые" экземпляры SimpleCub разделяются между 2-мя дочерними потоками (находясь в dic1 и dic2), они immutable экземпляры. При добавлении новых SimpleCub созданных в дочерних потоках вызывается только GetHashCode этих новых экземпляров. Т.е никаких накладных расходов/коллизий здесь не может быть со "старыми" экземплярами SimpleCub в дочерних потоках полученных от родительского потока.
Re[6]: Синхронизация на доступ при добавлении объекта
От: Аноним  
Дата: 11.03.10 13:24
Оценка:
Здравствуйте, samius, Вы писали:

S>Отлично. Только лучше int заменить на long и потом взять t.GetHashCode(). Тогда старшие байты координат не потеряются.

Спасибо Вам за помощь.
Re: Синхронизация на доступ при добавлении объекта
От: hooky-mars  
Дата: 11.03.10 13:31
Оценка:
Единственное, что тут можно предположить это работа с листами. Если на момент добавления объектов из листов в диктионари, в радительском потоке возможна работа с этими листами, то тогда надо лочить листы.
Или я, что не так понял?
Re[2]: Синхронизация на доступ при добавлении объекта
От: Аноним  
Дата: 11.03.10 13:48
Оценка:
Здравствуйте, hooky-mars, Вы писали:

HM>Единственное, что тут можно предположить это работа с листами. Если на момент добавления объектов из листов в диктионари, в радительском потоке возможна работа с этими листами, то тогда надо лочить листы.

HM>Или я, что не так понял?
Здесь проблем нет. После того как list1 и list2 переданы в дочерние потоки, в родительском потоке с ними нет никаких операций.
Re[5]: Синхронизация на доступ при добавлении объекта
От: Jolly Roger  
Дата: 11.03.10 13:58
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Jolly Roger, Вы писали:


JR>>Ну а что именно Вы собираетесь лочить? У Вас, как я понял, есть готовый класс и не менее готовый словарь. Покажите псевдокодом, в каком именно месте Вы собираетесь ставить влокировку и поясните, от каких ситуаций она, по Вашему мнению, должна Вас эащитить.


А>Хоть "старые" экземпляры SimpleCub разделяются между 2-мя дочерними потоками (находясь в dic1 и dic2), они immutable экземпляры. При добавлении новых SimpleCub созданных в дочерних потоках вызывается только GetHashCode этих новых экземпляров. Т.е никаких накладных расходов/коллизий здесь не может быть со "старыми" экземплярами SimpleCub в дочерних потоках полученных от родительского потока.


Мне это понятно Это-же Вы вроде как высказывали сомнения здесь
Автор:
Дата: 11.03.10
Нет?
"Нормальные герои всегда идут в обход!"
Re[6]: Синхронизация на доступ при добавлении объекта
От: Аноним  
Дата: 11.03.10 14:19
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

А>>Хоть "старые" экземпляры SimpleCub разделяются между 2-мя дочерними потоками (находясь в dic1 и dic2), они immutable экземпляры. При добавлении новых SimpleCub созданных в дочерних потоках вызывается только GetHashCode этих новых экземпляров. Т.е никаких накладных расходов/коллизий здесь не может быть со "старыми" экземплярами SimpleCub в дочерних потоках полученных от родительского потока.


JR>Мне это понятно Это-же Вы вроде как высказывали сомнения здесь
Автор:
Дата: 11.03.10
Нет?


Да высказывал
Но потом с помощью Ваших наводящих вопросов разобрался в ситуации.
Спасибо Вам за помощь.
Re: Синхронизация на доступ при добавлении объекта
От: Visor2004  
Дата: 11.03.10 17:03
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Добрый день,

А>Вопрос:
А>Нужна ли блокировка(синхронизация) при добавлении элементов в dic1 и dic2 ?

Если никаких операций над элементами не делается, кроме добавления в таблицы, то никакой синхронизации не надо. ибо разделяемых данных нету.
Помните!!! ваш говнокод кому-то предстоит разгребать.
Re[2]: Синхронизация на доступ при добавлении объекта
От: olegkr  
Дата: 12.03.10 21:43
Оценка:
Здравствуйте, samius, Вы писали:

S>Я фигею с такого GetHashCode()!!!


А я с calcHash
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.