|
|
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 17:59 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
сорри Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 18:00 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
И... В чем смысл топика? Да и вообще, приведенный Вами код работает? Что мне он кажется _ну_крайне_ странным. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 18:11 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Leonid KudryavtsevИ... В чем смысл топика? Да и вообще, приведенный Вами код работает? Что мне он кажется _ну_крайне_ странным. потренироваться писать многопоточный код) Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. я добавил логов и вроде всё работает. только он конечно blocking, название кривое. Собсно с учетом отсутвия опыта написания многопоточнго кода в продакшене и возникла мысль показать что есть тут. Вдруг будет аргументированная критика. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 18:19 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questioner Код: java 1. а как же тонкая оптимизация с использованием volatile -переменных? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 18:23 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Usmanquestioner Код: java 1. а как же тонкая оптимизация с использованием volatile -переменных? Ок, попробую написать ещё и неблокирующий алгоритм. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 18:24 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Я только не понял, нафига там куча wait и notify. Нафига оно надо и что оно должно было делать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 18:28 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Leonid KudryavtsevЯ только не понял, нафига там куча wait и notify. Нафига оно надо и что оно должно было делать. 1. Чтобы поток подвис до появления значения в очереди пока она пустая 2. Если очередь переполнена, то ждём пока освободится место ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 18:36 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questioner1. Чтобы поток подвис до появления значения в очереди пока она пустая 2. Если очередь переполнена, то ждём пока освободится место Leonid KudryavtsevДа и вообще, приведенный Вами код работает? Что-то мне он кажется _ну_крайне_ странным. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 18:38 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Leonid Kudryavtsev, Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. можете запустить. Но конечно это не значит, что код всегда корректно работает. А что конкретно не нравится то? а то без аргументов хейтить это неконструктивно ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 18:41 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
1. Конструктор не thread safe 2. Сочетание NonBlocking и IterruptedException в интерфейсе это прикольно :o) 3. Ну и вообще с synchronized не интересно 4. Как уже заметили, это самый что ни на есть blocking ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 18:44 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
На мой IMHO приведенный Вами код stack'а совершенно "странный" Ваш код который его "проверяет" еще более страннее. Складывается впечатление, что Вы вообще не знаете значения слова "многопотоковость" и "многопоточное выполнение" в практическом его смысле. Обсуждать при этом такие слова как "потокобезопасность" даже страшно. Т.ч., что тут критиковать, я даже не знаю. questionerможете запустить. Не собираюсь. Банально лениво. Всякий мусор на компьютере запускать. Да и зачем? Где тут многопоточное выполнение? Что этот код делает? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 18:55 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Leonid KudryavtsevГде тут многопоточное выполнение? А не, беру свои слова обратно. "Многопоточность" тут конечно есть, частично. Но именно, что частично. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 19:00 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Leonid KudryavtsevНа мой IMHO приведенный Вами код stack'а совершенно "странный" Ваш код который его "проверяет" еще более страннее. Складывается впечатление, что Вы вообще не знаете значения слова "многопотоковость" и "многопоточное выполнение" в практическом его смысле. Обсуждать при этом такие слова как "потокобезопасность" даже страшно. Т.ч., что тут критиковать, я даже не знаю. questionerможете запустить. Не собираюсь. Банально лениво. Всякий мусор на компьютере запускать. Да и зачем? Где тут многопоточное выполнение? Что этот код делает? складывается впечатление, что Вам просто поворчать не на кого) или четко выразить свою мысли Вы не можете. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 19:03 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
no568921. Конструктор не thread safe 2. Сочетание NonBlocking и IterruptedException в интерфейсе это прикольно :o) 3. Ну и вообще с synchronized не интересно 4. Как уже заметили, это самый что ни на есть blocking Вот это аргументированная критика. no568921. Конструктор не thread safe что конкретно не так с конструктором? какие проблемы могут быть? мне кажется synchronized даёт все необходимые гарантии no568922. Сочетание NonBlocking и IterruptedException в интерфейсе это прикольно :o) всё-таки это Blocking конечно ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 19:07 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Leonid Kudryavtsev, Ну тут можно юзать ReadWriteLock явно, но мне это уже неинтересно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 19:09 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Чтобы не было разночтений с именами - последняя версия: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 19:13 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questionerили четко выразить свою мысли Вы не можете. Выражаюсь четче. На мой взгляд, "Многопоточность" это ОДНОВРЕМЕННОЕ выполнение какого либо кода Если уж Вы пишите проверку для своей поделки, то хорошо, было бы, если бы она "многопоточность" и проверяла. Особенно, если Вы уверяете: 1. Чтобы поток подвис до появления значения в очереди пока она пустая 2. Если очередь переполнена, то ждём пока освободится место В общем, проверьте ситуацию, когда один поток вставляет данные, а другой ОДНОВРЕМЕННО их оттуда считывает. Да при этом, что бы и проявлялась ситуация описанная Вами же. Пока, наблюдается совершенно странный полуторно-поточный тестовый код. ПОСЛЕДОВАТЕЛЬНО: 1. Добавляющий данные в коллекцию (тут правда, хоть что-то многопоточное присудствует) 2. ПОСЛЕДОВАТЕЛЬНО (т.к. Вы зачем-то sleep внутрь цикла вставили) считывающий данные из коллекции. На что встречный вопрос: где в Вашем коде проверки хоть какая-то адекватная многопоточность? И что тут можно обсуждать? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 19:19 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Leonid Kudryavtsev, такой вариант я тоже проверял, работает. последний раз немного модифицировал код, чтобы удостовериться, что если очередь переполнена, то значения никуда не пропадают ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 19:26 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Кстати неблокирующий вариант возможен с обычным List ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 19:38 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
По моим наблюдениям это самая вредная ошибка плохих программистов. Не то, что они программируют плохо, а что они программируют то, что не надо программировать. Обсуждать тут нечего. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 20:01 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questionerКстати неблокирующий вариант возможен с обычным List ? Код: java 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 20:08 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questioner, Насчет wait/notify, это я ошибся. Сорри. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 20:43 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Partisan MПо моим наблюдениям это самая вредная ошибка плохих программистов. Не то, что они программируют плохо, а что они программируют то, что не надо программировать. Обсуждать тут нечего. Это задание просто потренироваться. Говорю же нет опыта написания в проде многопоточнго кода. Я пишу это не потому, что мне очередь нужна, а потому, что мне нужен навык. Можете предложить и другие задания, если они будут лучше я только рад. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 21:59 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
UsmanquestionerКстати неблокирующий вариант возможен с обычным List ? Код: java 1. ну а что если так: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 23:18 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
хотя это всё равно не позволит несколько читателей сразу... надо ещё подумать ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 23:19 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
авторчто конкретно не так с конструктором? какие проблемы могут быть? мне кажется synchronized даёт все необходимые гарантии А где у вас hb между вызовом конструктора и вызовом методов pop/push...? В предыдущей теме столько обсуждали... Еще добавлю про Ваш код - обычно размер стека динамический, т.е. заранее не задается, в таком случае нафига мьютекс на запись? Ок, мы оставляем синхронайзд только для notify, но тут проблема - у нас то, где хранятся элементы совсем не конкаррент. Поэтому я бы сделал так: Вот это lock-free стэк: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. А вот так - тот BlockingStack, который Вам и нужен: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. questioner, Вам вот задание (ну Вы же сами просили) - написать метод size() для ConcurrentStack. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 23:30 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Чего-то я тупанул, всё оба действия ведь модифицируют коллекцию, соответственно 2 потока одновременно не могут производить операции Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 23:38 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
вот такой вариант наверное будет работать, но медленно: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.02.2017, 23:53 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
no56892 Еще добавлю про Ваш код - обычно размер стека динамический, т.е. заранее не задается, в таком случае нафига мьютекс на запись? Ок, мы оставляем синхронайзд только для notify, но тут проблема - у нас то, где хранятся элементы совсем не конкаррент. Не понял причинно-следственной связи. мы оставляем synchronized дабы исключить параллельное изменение коллекции потоками. no56892 Поэтому я бы сделал так: Вот это lock-free стэк: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. Вроде да, должно работать, но по-моему это то же самое, что я написал(спору нет, после Вас). А вот так - тот BlockingStack, который Вам и нужен: no56892 Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. я не понял идею. явно где-то не хватает semaphore.take() авторquestioner, Вам вот задание (ну Вы же сами просили) - написать метод size() для ConcurrentStack.[/quote] Судя по всему надо, чтобы никто не работал в этот момент. Сейчас придумаю ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 00:12 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
ну и кстати концептуальный вопрос ещё: конструкция вида: Код: java 1. 2. 3. 4. //2 Как я понимаю мы пытаемся симулировать ситуацию, что между //1 и //2 никаких действий не произошло. Но ведь за это время мог элемент добавиться и удалиться, а в итоге состояние то же с точки зрения нашей проверки. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 00:41 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questioner Но ведь за это время мог элемент добавиться и удалиться, а в итоге состояние то же с точки зрения нашей проверки. Гугли по ключевым словам проблема ABA ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 00:52 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
забыл никquestionerНо ведь за это время мог элемент добавиться и удалиться, а в итоге состояние то же с точки зрения нашей проверки. Гугли по ключевым словам проблема ABA В языках с управляемой памятью не критично, в данном случае все будет ок ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 00:57 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
авторНе понял причинно-следственной связи. мы оставляем synchronized дабы исключить параллельное изменение коллекции потоками. Написал немного не то, что хотел сказать авторВроде да, должно работать, но по-моему это то же самое, что я написал(спору нет, после Вас). Это совершенно разные вещи, Вы написали опять с локами, только в отличие от первого варианта с synchronized (который, кстати хотя бы работает), здесь у Вас формально CAS, но только формально, в Вашей реализации это те же локи. Написать над методом non blocking и вставиеь busy-wait - это мощно. авторя не понял идею. явно где-то не хватает semaphore.take() В Java SE API)) авторСудя по всему надо, чтобы никто не работал в этот момент. Сейчас придумаю Опять локи? По коду: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. Если срабатывает условие (A) весь стэк навесгда в busy-wait...Ну и немного не понятное у Вас Апи - через offer мы не можем больше max положить, а через put - можем? Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. (A) - допустим у нас есть 1+ элементов в стэке уже и один поток уже получил лок и кладет его туда, тоесть получается вернет null? Хотя там есть элементы... Нафига AtomicBoolean volatile? Конструктор не safe с точки зрения JLS, хотя на практике спасет хотя бы одно final поле, но я бы так не писал. Ну и все эти Код: java 1. 2. 3. ничем не отличаются от lock.lock()/unlock() кроме того, что забываете unlock делать. авторКак я понимаю мы пытаемся симулировать ситуацию, что между //1 и //2 никаких действий не произошло. Если произошло - повторяем цикл заново. "!" забыли. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 01:12 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
no56892ничем не отличаются от lock.lock()/unlock() кроме того, что забываете unlock делать Ну и еще невозможностью "интерраптнуть" ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 01:16 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
no56892no56892ничем не отличаются от lock.lock()/unlock() кроме того, что забываете unlock делать Ну и еще невозможностью "интерраптнуть" Нет, такое использование еще даже хуже - процессор жрет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 01:27 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
забыл никзабыл никпропущено... Гугли по ключевым словам проблема ABA В языках с управляемой памятью не критично, в данном случае все будет ок Да, я гуглил и видел фразу, что в языках с gc ее тяжело воспроизвести. Почему в данном случае все ок будет? Проверка ведь будет успешной. Смотрите, еще раз, сценарий такой: 1.Первый поток запомнил head 2. Далее другие потоки успели добавить и удалить элемент из стекла 3. Первый поток проверяет, что old == pointer и цикл кончится Почему мы здесь эту проблему не получим? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 09:40 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questionerВдруг будет аргументированная критика. Ну, 1. Если назвать NonBlocking и потом все на synchronized методах это сильно. 2. Долго выяснять зачем ставить final на поля типа list и maxsize и не сделать этого. 3. Размер списка не уменьшается, мелочь конечно, но тогда почему бы не Код: java 1. 4. remove само по себе возвращает объект, повторный поиск лишний. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 09:58 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questionerхотя это всё равно не позволит несколько читателей сразу... надо ещё подумать А нафиг стеку параллельные читатели-писатели? Овчинка выделки не стоит. P.S. И мне кажется что массива с указателем текущего положения будет вполне достаточно, ArrayList практически не нужен. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 10:01 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
А главное, кого будум ждать, если тот, кто должен сделать следующий pull пытается сделать push, а стек переполнен. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 10:10 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Кстати про remove. Если один и тот же объект у тебя лежит два раза в list. Что будет по remove(t)? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 10:17 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Сергей АрсеньевquestionerВдруг будет аргументированная критика. Ну, 1. Если назвать NonBlocking и потом все на synchronized методах это сильно. это уже обсудили, Вы не дочитали Сергей Арсеньев 2. Долго выяснять зачем ставить final на поля типа list и maxsize и не сделать этого. Похоже и там и там правда нужен. Была мысль, что раз меняем в sync секции, то и не надо, но начальная инициализация может ускользнуть Сергей Арсеньев 3. Размер списка не уменьшается, мелочь конечно, но тогда почему бы не Код: java 1. такая задача не ставилась Сергей Арсеньев 4. remove само по себе возвращает объект, повторный поиск лишний. согласен, но не этот аспект был интересен, поэтому не заморчивался Сергей АрсеньевЕсли один и тот же объект у тебя лежит два раза в list. Что будет по remove(t)? удалится первый, а нужен последний, согласен, но, эти кейсы не столь интересны для меня в этой задаче ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 10:31 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questionerудалится первый, а нужен последний, согласен, но, эти кейсы не столь интересны для меня в этой задаче Для начала надо понять задачу, а потом ее параллелить. Это основной принцип. Если Вы не уделяете внимания тому, что делаете что вставляем, что удаляем, то браться за параллельное выполнение этих действий - только плодить множество ошибок. Да и сам выбор задачи не удачен. Профита от неблокирования тут никакого. Тут еще есть смысл в подборе правильной блокировки, поиске зацикливаний и т.п., но не более того. В смысле неблокирующих операций лучше посмотреть на вариант перевода средств между счетами типа списать у Иванова 10 записать Петрову (желательно, чтоб денег хватало, не было бы взаимоблокировок и чтоб Сидоров не обогатился на этом). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 11:06 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
забыл никзабыл никпропущено... Гугли по ключевым словам проблема ABA В языках с управляемой памятью не критично, в данном случае все будет ок а тут пишут, что вполне может http://www.ibm.com/developerworks/library/j-jtp11234/ ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 11:49 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
no56892, no56892Это совершенно разные вещи, Вы написали опять с локами, только в отличие от первого варианта с synchronized (который, кстати хотя бы работает), здесь у Вас формально CAS, но только формально, в Вашей реализации это те же локи. Написать над методом non blocking и вставиеь busy-wait - это мощно. а вот я правда не очень понимаю чем мой цикл от Вашего отличается. Насчёт дырок в логике, да, всё верно. скопирую рядом: Код: java 1. 2. 3. 4. 5. 6. 7. 8. Код: java 1. 2. 3. 4. 5. 6. по-моему у Вас наоборот плохо в цикле, что каждый раз новый объект создаётся. у меня вот один раз я захватил всё добро и только тогда делаю объек, хотя это время лока удлиняет. наверное один раз заранее лучше сделать ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 12:00 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questionerзабыл никпропущено... В языках с управляемой памятью не критично, в данном случае все будет ок а тут пишут, что вполне может http://www.ibm.com/developerworks/library/j-jtp11234/ Опять видимо в ваших фантазиях. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 12:01 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
забыл никquestionerпропущено... а тут пишут, что вполне может http://www.ibm.com/developerworks/library/j-jtp11234/ Опять видимо в ваших фантазиях. аргументированно ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 12:03 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questionerno56892, no56892Это совершенно разные вещи, Вы написали опять с локами, только в отличие от первого варианта с synchronized (который, кстати хотя бы работает), здесь у Вас формально CAS, но только формально, в Вашей реализации это те же локи. Написать над методом non blocking и вставиеь busy-wait - это мощно. а вот я правда не очень понимаю чем мой цикл от Вашего отличается. Насчёт дырок в логике, да, всё верно. скопирую рядом: Код: java 1. 2. 3. 4. 5. 6. 7. 8. Код: java 1. 2. 3. 4. 5. 6. по-моему у Вас наоборот плохо в цикле, что каждый раз новый объект создаётся. у меня вот один раз я захватил всё добро и только тогда делаю объек, хотя это время лока удлиняет. наверное один раз заранее лучше сделать Мысли спутались пока писал)) у меня ж нет объекта никакого нового, мне его передают. а у Вас было бы оптимальнее создать объект до цикла, в начале цикла взять струю голову, у созданного объекта настроить ссылку на старый и вызвать CAS ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 12:13 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questionerзабыл никпропущено... Опять видимо в ваших фантазиях. аргументированно Мусор на входе = мусор на выходе ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 12:16 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
забыл никquestionerпропущено... аргументированно Мусор на входе = мусор на выходе я ссылку привел. вот цитата из нее: http://www.ibm.com/developerworks/library/j-jtp11234/ The ABA problem Because CAS basically asks "is the value of V still A" before changing V, it is possible for a CAS-based algorithm to be confused by the value changing from A to B and back to A between the time V was first read and the time the CAS on V is performed. In such a case, the CAS operation would succeed, but in some situations the result might not be what is desired. (Note that the counter and mutex examples from Listing 1 and Listing 2 are immune to this problem, but not all algorithms are.) This problem is called the ABA problem, and is generally dealt with by associating a tag, or version number, with each value to be CASed, and atomically updating both the value and the tag. The AtomicStampedReference class provides support for this approach. Статья про атомики ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 12:18 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
no56892Вот это lock-free стэк: Это ,так называемый, lock-free стэк. Ибо 1. compareAndSet - это и есть блокировка, просто она wait free. Вслед за этим все заворачивается в цикл, который как раз и реализует это ожидание. Поэтому алгоритм не "без блокировок" и не "без ожиданий". 2. Это даже не стек. Ибо в силу отсутствия сериализации вполне допускается ситуация, когда поток будет пытаться вставить элемент, но у него это достаточно долго не будет получаться, при том, что другие потоки будут вставлять и вынимать объекты из "стека". 3. Гонять в цикле генератор новый Entry, при том, что достаточно менять одну ссылку это перебор. 3а. Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. При пустом стеке может забрать новый элемент. Что, правда, может и не плохо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 12:27 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questionerзабыл никпропущено... Мусор на входе = мусор на выходе я ссылку привел. вот цитата из нее: Я видел, не поленился даже поискать, и только после этого и ответил. Как это расходится с моими словами? Где там хоть слово про стэк и managed память? Все зависит от алгоритма. В unmanaged языках существует дополнительная проблема, когда поток держит ссылку, которая уже удалена другим потоком и потом может внезапно обновиться ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 12:28 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questionerСтатья про атомики В данном случае, никогда не будет удачной попытки вставить один и тот же элемент (Entry) в силу этого и не может повторно оказаться та же величина для сравнения. Просто реализовывать свою блокировку на атомиках через true false, а безсмысленно, б уж лучше id потока использовать на предмет кто последний захватил, типа Код: java 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 12:39 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Сергей Арсеньев, Точнее может, но это не важно, в этом случае нам не важно, что в промежутке вершина стека менялась, главное, что на этот момент она там же и ничего ниже ее не вынималось. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 12:43 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Сергей АрсеньевВ данном случае, никогда не будет удачной попытки вставить один и тот же элемент почему? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 13:13 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Сергей Арсеньев, тогда операция ведь формально не атомарно. между взятием старого значения и проверкой могло произойти вставка ещё 100 элементов сверху и 101-ым вставили опять старый элемент ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 13:16 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
А чем не нравится https://docs.oracle.com/javase/7/docs/api/java/util/Stack.html ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 13:19 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questionerСергей Арсеньев, тогда операция ведь формально не атомарно. между взятием старого значения и проверкой могло произойти вставка ещё 100 элементов сверху и 101-ым вставили опять старый элемент И что это меняет? Вам вот правильно говорят, сначала определитесь как алгоритм в вашем понимании должен ПРАВИЛЬНО работать. Есть fair-locking, когда важно в каком порядке будут вставляться элементы(или изменяться shared объекты), а когда необходима просто консистентность. В вашем случае нужна просто консистентность, так что неважно что еще 100 потоков там что-то надобавлялт, структура ведь остается корректной ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 13:22 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
забыл ника когда необходима просто консистентность. Читать как "а есть non-fair когда необходима просто консистентность." ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 13:23 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questionerмежду взятием старого значения и проверкой могло произойти вставка ещё 100 элементов сверху и 101-ым вставили опять старый элемент Поэтому вставляют и сравнивают не сам элемент, а Entry. Которое по сути является ссылкой на этот элемент и на предыдущее Entry. Entry для каждой вставки новое. Да алгоритм проигнорирует ситуацию, когда прошло 100 (n) вставок и 100 (n) забираний элементов между получением старой вершины и попыткой вставки новой. Но в данном случае это не важно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 13:25 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Сергей Арсеньевquestionerмежду взятием старого значения и проверкой могло произойти вставка ещё 100 элементов сверху и 101-ым вставили опять старый элемент Поэтому вставляют и сравнивают не сам элемент, а Entry. Которое по сути является ссылкой на этот элемент и на предыдущее Entry. Entry для каждой вставки новое. Да алгоритм проигнорирует ситуацию, когда прошло 100 (n) вставок и 100 (n) забираний элементов между получением старой вершины и попыткой вставки новой. Но в данном случае это не важно. это меткое замечание ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 13:29 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
забыл ник структура ведь остается корректной Для понятия "стек" важен порядок вставки и забирания элементов (LIFO). Если он не важен, то это уже не стек. Более того, в силу того, что в отличии от очереди, тут не получится даже развести читателя и писателя (они конкурируют за право изменить один и тот же указатель). А действий, которые надо совершить (проверка заполненности, изменение указателя вершины, возможно обнуление старой ссылки, возврат значения), раз-два и обчелся. Смысла нет обойтись без блокировки - можно не не такой уж и выигрыш по скорости, плюс расходы на генерацию (и последующую работу GC) новых Entry (против массива и индекса вершины). Не та задача, где стоит ломать копья. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 13:36 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 13:42 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Сергей Арсеньевзабыл ник структура ведь остается корректной Для понятия "стек" важен порядок вставки и забирания элементов (LIFO). Если он не важен, то это уже не стек. Более того, в силу того, что в отличии от очереди, тут не получится даже развести читателя и писателя (они конкурируют за право изменить один и тот же указатель). А действий, которые надо совершить (проверка заполненности, изменение указателя вершины, возможно обнуление старой ссылки, возврат значения), раз-два и обчелся. Смысла нет обойтись без блокировки - можно не не такой уж и выигрыш по скорости, плюс расходы на генерацию (и последующую работу GC) новых Entry (против массива и индекса вершины). Не та задача, где стоит ломать копья. Эмм, а кто спорит? Если вы про то что я криво вас процитировал, то это глюк сайта, я отвечал ТС. Видимо ему бороться с ветряными мельницами просто необходимо ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 13:50 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
забыл никquestionerСергей Арсеньев, тогда операция ведь формально не атомарно. между взятием старого значения и проверкой могло произойти вставка ещё 100 элементов сверху и 101-ым вставили опять старый элемент И что это меняет? Вам вот правильно говорят, сначала определитесь как алгоритм в вашем понимании должен ПРАВИЛЬНО работать. Есть fair-locking, когда важно в каком порядке будут вставляться элементы(или изменяться shared объекты), а когда необходима просто консистентность. В вашем случае нужна просто консистентность, так что неважно что еще 100 потоков там что-то надобавлялт, структура ведь остается корректной У меня диссонанс из-за того, что атомики не атомарны в моём понимании(наверное оно ошибочно) когда меня спрашивают на собесах что это такое и зачем они нужны я даю ответ, что они нужны для того, чтобы другой поток не вклинился между двумя операциями (increment and get допустим)? и я так понимал код, что между взятием старого значения и присвоением нового ничего не должно произойти, иначе новый цикл. а тут не совсем так получается. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 13:57 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
забыл никЭмм, а кто спорит? Если вы про то что я криво вас процитировал, то это глюк сайта, я отвечал ТС. Видимо ему бороться с ветряными мельницами просто необходимо пфф, я изучаю инструмент, не более того ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 14:02 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questionerУ меня диссонанс из-за того, что атомики не атомарны в моём понимании(наверное оно ошибочно) У Атомика есть куча операций, которые атомарны. Не более не менее. Между ними никакой атомарности никто не обещал. Для этого: ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 14:05 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Сергей АрсеньевquestionerУ меня диссонанс из-за того, что атомики не атомарны в моём понимании(наверное оно ошибочно) У Атомика есть куча операций, которые атомарны. Не более не менее. Между ними никакой атомарности никто не обещал. Для этого: ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 14:14 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questionerУ нас тут явно недопонимание По шагам. У атомика есть ряд атомарных операций. 1. pointer.get(); Атомарно 2. pointer.compareAndSet(currentTop, newTop); Атомарно Но никто не обещает Атомарность этих действий вместе. Поэтому между ними может вклинится кто-то другой. Сам по себе atomic не ведет учет своего состояния, поэтому нет операции ifNotChangedSet(). Делается через проверку старого значения. Но совпадение старого значения, не означает что состояние не менялось. В случае вставки в стек это все равно - при farness это не важно, главное, что вставляем в вершину. А это Atomic гарантирует, если это уже не тот экземпляр, то присвоения не будет (для этого у ней внутре миниблокировка, со всеми h-b бонусами, в отличии от weakCompareAndSet). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 14:28 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
автор1. compareAndSet - это и есть блокировка, просто она wait free. Вслед за этим все заворачивается в цикл, который как раз и реализует это ожидание. Поэтому алгоритм не "без блокировок" и не "без ожиданий". Строго говоря, это lock-free называется, см. http://www.1024cores.net/home/in-russian/lock--wait--obstruction--atomic-free-algorithms автор2. Это даже не стек. Ибо в силу отсутствия сериализации вполне допускается ситуация, когда поток будет пытаться вставить элемент, но у него это достаточно долго не будет получаться, при том, что другие потоки будут вставлять и вынимать объекты из "стека". Это starvation, есть такое, но из этого не следует, что это перестает быть стеком, следуя такой логике Collections.synchronized(deque) это тоже не стек, да и ConcurrentLinkedDeque тоже не стек. авторГонять в цикле генератор новый Entry, при том, что достаточно менять одну ссылку это перебор. + авторПри пустом стеке может забрать новый элемент. Что, правда, может и не плохо. +, надо добавить else return null; Да, кстати, а как наличие GC отменяет ABA? Вполне теоретически возможна ситуация, когда Entry собирается GC и new Entry возвращает объект по тому же адресу. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 16:32 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
no56892Это starvation, есть такое, но из этого не следует, что это перестает быть стеком, следуя такой логике Collections.synchronized(deque) это тоже не стек, да и ConcurrentLinkedDeque тоже не стек. Ты не поверишь, но и java.util.Stack тоже не гарантирует порядка в этом вопросе. :) А так да. no56892Да, кстати, а как наличие GC отменяет ABA? Вполне теоретически возможна ситуация, когда Entry собирается GC и new Entry возвращает объект по тому же адресу. Ну если Entry не пересоздавать в цикле ожидания, то проблемы быть не должно.:) Ибо GC он не достанется, так как удерживается переменной в стеке потока, а то, что добавлено в "стек" удерживается "стеком". ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 17:46 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Только Entry надо создать до pointer.get(); ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 17:50 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Сергей Арсеньев, это я перемудрил ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 17:51 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
авторНу если Entry не пересоздавать в цикле ожидания, то проблемы быть не должно.:) Ибо GC он не достанется, так как удерживается переменной в стеке потока, а то, что добавлено в "стек" удерживается "стеком". Да, точно, я тупанул questioner, ну, что, придумал как написать size()?)) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 17:55 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Код: java 1. До этого момента Entry держится pointer, потом currentTop. Поэтому, эта ссылка не может собраться и выдаться еще кому-нибудь. Поэтому, повторно в стек попасть не может вплоть до конца цикла. А compareAndSet(currentTop, newTop) раньше. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 18:00 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
no56892questioner, ну, что, придумал как написать size()?)) так наверное: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 21:44 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
хотя cas операция тут как-то ни к селу ни к городу. обычный if можно написать. Меня чего-то терзают смутные сомнения в нужности cas в данном случае ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 22:09 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questionerМеня чего-то терзают смутные сомнения в нужности cas в данном случае Забей. size() вполне может устареть к моменту возврата результата. Тут важно гарантировать, что цепочка не порвется или еще хуже -сама замкнется, пока по ней бегут. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.02.2017, 23:14 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Сергей АрсеньевquestionerМеня чего-то терзают смутные сомнения в нужности cas в данном случае Забей. size() вполне может устареть к моменту возврата результата. Тут важно гарантировать, что цепочка не порвется или еще хуже -сама замкнется, пока по ней бегут. Хм, тогда мой вариант совсем не будет работать. Тогда либо как-то(не знаю как) лочить коллекцию целиком на время исполнения метода, либо держать atomicLong который будет трекать pop/push. Но опять же данные могут быть слегка неконсистентные. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 00:22 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questioner, Реализация метода size() в SynchronizedCollection<E> : Код: java 1. 2. 3. P.S. SynchronizedCollection<E> - synchronized-обертка на обычной коллекцией. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 05:08 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Usman, В Synchronizedxxx все методы синхронизированы, поэтому и работать будет, а тут ведь просят для неблокирубщего алгоритма, тут скорее надо смотреть в сторону CHM ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 09:25 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Usman, Но тогда можно пользоваться только синхро коллекцией. А в чем смысл? questioner, Но поскольку Entry не меняются после добавления в стек, даже при извлечении объекта из стека, то цепочка не разорвется. Даже если извлечения обгонят size(). И потому, что size() будет их удерживать их не соберет GC. Единственное но - при многопоточной работе, size() всегда имеет справочный характер и может устареть в любой момент, в т.ч. до возврата результата. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 09:25 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Хочешь задачку? Сделать аналогичный "стек", позволяющий вынуть как одно, так и два значения подряд. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 09:27 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Сергей АрсеньевUsman, Но тогда можно пользоваться только синхро коллекцией. А в чем смысл? questioner, Но поскольку Entry не меняются после добавления в стек, даже при извлечении объекта из стека, то цепочка не разорвется. Даже если извлечения обгонят size(). И потому, что size() будет их удерживать их не соберет GC. Единственное но - при многопоточной работе, size() всегда имеет справочный характер и может устареть в любой момент, в т.ч. до возврата результата. Кстати да, при таком подходе, объекты не будут удаляться из памяти. Memory leak. OutOfMemory может быть ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 09:33 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questioner, Почему же? Всю цепочку держит голова. Как она спускается по цепочке - объект становится собираемым. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 09:56 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Сергей Арсеньевquestioner, Почему же? Всю цепочку держит голова. Как она спускается по цепочке - объект становится собираемым. Хм, действительно ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 11:10 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questioner Хм, действительно Ну что, пора уже к Art of Multiprocessor programming приступать?:) Эта книга сложная но must-read. Ну и упражнений там куча ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 11:15 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Сергей АрсеньевХочешь задачку? Сделать аналогичный "стек", позволяющий вынуть как одно, так и два значения подряд. Как он должен себя если просят вынуть два значения, а есть только одно? в каком формате их выплёвывать? в массиве? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 14:03 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questionerВ Synchronizedxxx все методы синхронизированы, поэтому и работать будет, а тут ведь просят для неблокирубщего алгоритмаСергей АрсеньевНо тогда можно пользоваться только синхро коллекцией. А в чем смысл?Ок. Можно завести одну переменную, которая и будет хранить общее кол-во элементов. Увеличивать при добавлении, уменьшать при удалении и т.д. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 14:12 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
UsmanОк. Можно завести одну переменную, которая и будет хранить общее кол-во элементов. Увеличивать при добавлении, уменьшать при удалении и т.д. http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1249068&msg=20190919 ..... либо держать atomicLong который будет трекать pop/push. Но опять же данные могут быть слегка неконсистентные. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 14:46 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questionerНо опять же данные могут быть слегка неконсистентные.это зависит от реализации pop/push ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 14:49 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
UsmanquestionerНо опять же данные могут быть слегка неконсистентные.это зависит от реализации pop/push Но в любом случае, если не запретить эти операции до запроса, результат может быть не актуальным. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 15:17 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Сергей АрсеньевUsmanпропущено... это зависит от реализации pop/push Но в любом случае, если не запретить эти операции до запроса, результат может быть не актуальным.В отличии от чтения, запись всегда должна быть блокирующей. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 15:22 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Usman, Мы про подсчет количества? Еще раз повторю - если не запретить изменения результат может быть не актуален чуть ранее чем известен. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 15:30 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Сергей Арсеньев, Поясните разницу между блокировкой и запретом? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 15:37 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Usman, Синонимы. Я про то, что блокировку надо ставить тогда до начала size() и не отменять, пока результат не будет применен. А этого тут хотели бы избежать. :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 16:23 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Сергей Арсеньевблокировку надо ставить тогда до начала size() и не отменять, пока результат не будет применен. А этого тут хотели бы избежать. :)Только в том случае, если подсчет елементов будет непосредственно внутри метода size(). Сергей Арсеньев, http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1249068&msg=20190919 atomicLong который будет трекать pop/pushА как на счет такого? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 16:33 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
UsmanСергей Арсеньевблокировку надо ставить тогда до начала size() и не отменять, пока результат не будет применен. А этого тут хотели бы избежать. :)Только в том случае, если подсчет елементов будет непосредственно внутри метода size(). Сергей Арсеньев, http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1249068&msg=20190919 atomicLong который будет трекать pop/pushА как на счет такого? ну так мы сможем этот atomicLong инкрементить только уже после того, как compareAndSet сработал. и соответственно действие будет не атомарно ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 17:13 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questionerну так мы сможем этот atomicLong инкрементить только уже после того, как compareAndSet сработал. и соответственно действие будет не атомарноИсхожу из этого:UsmanВ отличии от чтения, запись всегда должна быть блокирующей. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 17:24 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
UsmanТолько в том случае, если подсчет елементов будет непосредственно внутри метода size(). Это не важно. В любой момент в том числе и в момент возврата из метода size() ситуация может измениться и число будет не актуально. И даже раньше. К тому моменту, как любой счетчик вернет значение, оно уже может устареть. Поэтому либо полная остановка изменяющих нитей, либо не актуальность. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 18:15 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Сергей Арсеньев Поэтому либо полная остановка изменяющих нитей, либо не актуальность. Ну в теории ведь есть multi CAS, допустим хранить счетчик размера стэка в отдельном поле и CASиться по нему и верху стэка. Не практично само собой, так, чтоб дискуссию поддержать:) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 18:46 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Сергей АрсеньевНо тогда можно пользоваться только синхро коллекцией. А в чем смысл?Смысл в актуальности (: ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 19:00 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
забыл никСергей Арсеньев Поэтому либо полная остановка изменяющих нитей, либо не актуальность. Ну в теории ведь есть multi CAS, допустим хранить счетчик размера стэка в отдельном поле и CASиться по нему и верху стэка. Не практично само собой, так, чтоб дискуссию поддержать:) а как это сделать? одновременно CASиться по размеру и по неизменной голове стека? код, плиз ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 19:07 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questioner, Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. тынц ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 19:25 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Usman, а это на что ответ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 19:27 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questioner, По поводу реализации метода size() ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 19:29 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Тут на самом деле 3 варианта (по степени возростания консистентности (отражения реального положения дел в стеке)): 1. Тупо получить ссылку на топ и пройтись до null, просуммировав количество элементов Это O(n) 2. Добавить AtomicLong и перед put/pop инкрементить/декрементить Это O(1) 3. Добавить поле long index в Entry, и присваивать его в момент создания Entry, тогда получить размер будет - topPointer.get().index; Это тоже O(1). Здесь тоже возможна ситуация когда между topPointer.get() и получением поля index будет вставлен(ы) элемент(ы), но операций требуется значительно меньше, чем с AtomicLong. Мое имхо, мне больше нравится этот способ : ). В ConcurrentLinkedList по O(1) размер уже не вернешь видимо... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 20:50 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
no568923. Добавить поле long index в Entry, и присваивать его в момент создания Entry, тогда получить размер будет - topPointer.get().index; Это тоже O(1). Здесь тоже возможна ситуация когда между topPointer.get() и получением поля index будет вставлен(ы) элемент(ы), но операций требуется значительно меньше, чем с AtomicLong. Мое имхо, мне больше нравится этот способ : ). В ConcurrentLinkedList по O(1) размер уже не вернешь видимо... Ну взяли вы индекс - например 9, начали создавать Entry, заснули, пришло еще 3 потока, индекс уже 12, это не вариант ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 20:54 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
забыл никno568923. Добавить поле long index в Entry, и присваивать его в момент создания Entry, тогда получить размер будет - topPointer.get().index; Это тоже O(1). Здесь тоже возможна ситуация когда между topPointer.get() и получением поля index будет вставлен(ы) элемент(ы), но операций требуется значительно меньше, чем с AtomicLong. Мое имхо, мне больше нравится этот способ : ). В ConcurrentLinkedList по O(1) размер уже не вернешь видимо... Ну взяли вы индекс - например 9, начали создавать Entry, заснули, пришло еще 3 потока, индекс уже 12, это не вариант Индекс присваивается до CAS, если пришло еще 3 потока, то когда проснемся CAS не пройдет, цикл повторится и уже будем новый индекс вставлять... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 20:59 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questionerзабыл никпропущено... Ну в теории ведь есть multi CAS, допустим хранить счетчик размера стэка в отдельном поле и CASиться по нему и верху стэка. Не практично само собой, так, чтоб дискуссию поддержать:) а как это сделать? одновременно CASиться по размеру и по неизменной голове стека? код, плиз Ага, может еще и ключи от квартиры? Я же говорю, что в ТЕОРИИ. Просто лень напрягать мозги в выдуманной ситуации, то что метод size() в конкурентной коллекции может выдавать не всегда конкретные ответы, это разумный компромисс. Но, если бы вдруг мне понадобилось что-нибудь этакое, на multi-CAS, я бы начал смотреть вот отсюда - AtomicMarkableReference ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 21:05 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
no56892Индекс присваивается до CAS, если пришло еще 3 потока, то когда проснемся CAS не пройдет, цикл повторится и уже будем новый индекс вставлять... Я немного запутался о какой версии кода вы уже тут говорите:) Как у вас CAS от индекса зависит? Я к тому что compareAndSwapить будете? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 21:09 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
забыл ник, Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 21:20 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
UsmanСергей АрсеньевНо тогда можно пользоваться только синхро коллекцией. А в чем смысл?Смысл в актуальности (: А как синхроколлекция даст актуальность? Ведь в момент return число может стать уже не соответствующим действительности. В силу этого ни о какой актуальности речи не будет. Блокировка должна быть до конца применения значения size(), типа: Код: java 1. может вызвать NPE. Посему какая разница неправильный размер он был получен внутри или снаружи. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 21:38 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
забыл никЯ немного запутался о какой версии кода вы уже тут говорите:) Как у вас CAS от индекса зависит? Я к тому что compareAndSwapить будете? Он имеет ввиду, что присвоение одному AtomicReference (ссылки на голову) и увеличение другого AtomicInteger (счетчика) одновременно не сделаешь. А значит size на основе счетчика может вернуть не правду. Правда оно и не важно. :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 21:41 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Сергей Арсеньев, Конечно если не делать вариант, что Entry сразу хранит счетчик. :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 21:43 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Сергей Арсеньев Блокировка должна быть до конца применения значения size() В таком варианте да, а вот например: Код: java 1. 2. 3. вполне себе нормально ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 21:54 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
Сергей АрсеньевА как синхроколлекция даст актуальность?на момент возвращения будет актуальное значениеСергей АрсеньевВедь в момент return число может стать уже не соответствующим действительности.в момент выхода из синхро-блока (если потоки все еще "крутятся") Сергей АрсеньевВ силу этого ни о какой актуальности речи не будет.см. 20194593 : Код: plaintext Сергей АрсеньевБлокировка должна быть до конца применения значения size()А вот тут я соглашусь. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.02.2017, 22:17 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
no568922. Добавить AtomicLong и перед put/pop инкрементить/декрементить Это O(1) а можно ведь только однажды это сделать перед возвращением значения пользователю ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.02.2017, 00:46 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
забыл никНу взяли вы индекс - например 9, начали создавать Entry, заснули, пришло еще 3 потока, индекс уже 12, это не вариант Entry засунется только тогда, когда между ним и головой никто не успел всунуться. Если успели все одно Entry переделывать перед новой попыткой вставки. Так что метод относительно действенный. Если только не бесполезный. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.02.2017, 09:37 |
|
||
|
codereview самописный потокобезопасный stack
|
|||
|---|---|---|---|
|
#18+
questionerno568922. Добавить AtomicLong и перед put/pop инкрементить/декрементить Это O(1) а можно ведь только однажды это сделать перед возвращением значения пользователю Только вот то, что запрос значения может оказаться раньше инкремента/декремента может привести к тому, что значение будет чуть менее чем полностью отличаться от актуального. Что правда не важно. :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.02.2017, 09:42 |
|
||
|
|

start [/forum/topic.php?all=1&fid=59&tid=2123165]: |
0ms |
get settings: |
11ms |
get forum list: |
19ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
89ms |
get topic data: |
10ms |
get forum data: |
3ms |
get page messages: |
142ms |
get tp. blocked users: |
2ms |
| others: | 220ms |
| total: | 504ms |

| 0 / 0 |
