|
|
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Понятно, что Concurrency Vs multithreading это где-то рядом, но может всё таки есть какие-то отличия. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.04.2014, 11:37 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Если в двух словах, multithreading - это выполнение задачи в нескольких потоках в целом, это скорее как парадигма. Concurrency не может существовать без multithreading - и в нем рассматриваются вопросы по взаимодействию потоков в том числе гарантии видимости, целостности, корректности. Concurrency - это когда есть работа в нескольких потоках с одними и теми же данными. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.04.2014, 12:25 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Как по мне оба этих термина про одно и тоже ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.04.2014, 12:25 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
забыл ник, то есть когда я пишу thread.start() я думаю в основном о multithreading, а когда о wait/notify, то о concurrency ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.04.2014, 13:31 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90забыл ник, то есть когда я пишу thread.start() я думаю в основном о multithreading, а когда о wait/notify, то о concurrency ? не совсем, multithreading он же возможен и на одном ядре. Это способ разбить задачу на юниты, которые могут, но не обязаны выполняться параллельно. Concurrency же рассматривает как раз вопросы параллельного выполнения, и возникающие в связи с этим сложности, видимость, целостность, и тд ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.04.2014, 13:50 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
забыл ник, redwhite90то есть когда я пишу thread.start() я думаю в основном о multithreading забыл никmultithreading он же возможен и на одном ядре. Это способ разбить задачу на юниты, которые могут, но не обязаны выполняться параллельно. а где противоречие? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.04.2014, 14:35 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Мыши против сыра. Рок против наркотиков. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.04.2014, 15:28 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
забыл никне совсем, multithreading он же возможен и на одном ядре. Это способ разбить задачу на юниты, которые могут, но не обязаны выполняться параллельно. Concurrency же рассматривает как раз вопросы параллельного выполнения, и возникающие в связи с этим сложности, видимость, целостность, и тдНу видимость не гарантирована и на одноядерном процессоре. Отличие одноядерного процессора от многоядерного заключается в том, что не надо парится о когерентности кэшей. Но все остальное остается на своих местах - кэширование в регистрах, out-of-order execution, и т.д.. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.04.2014, 20:03 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
DEVcoach, я из без таких выражений, как "когерентности кэшей" верю, что ты разбираешься в этой теме) но можно ж как-то почеловечнее выражаться) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.04.2014, 11:17 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
DEVcoachзабыл никне совсем, multithreading он же возможен и на одном ядре. Это способ разбить задачу на юниты, которые могут, но не обязаны выполняться параллельно. Concurrency же рассматривает как раз вопросы параллельного выполнения, и возникающие в связи с этим сложности, видимость, целостность, и тдНу видимость не гарантирована и на одноядерном процессоре. Отличие одноядерного процессора от многоядерного заключается в том, что не надо парится о когерентности кэшей. Но все остальное остается на своих местах - кэширование в регистрах, out-of-order execution, и т.д.. DEVcoach, А как Вы "паритесь с когерентностью кэшэй" и что такое кэширование в регистрах? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.04.2014, 12:47 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
забыл никredwhite90забыл ник, то есть когда я пишу thread.start() я думаю в основном о multithreading, а когда о wait/notify, то о concurrency ? не совсем, multithreading он же возможен и на одном ядре. Это способ разбить задачу на юниты, которые могут, но не обязаны выполняться параллельно. Concurrency же рассматривает как раз вопросы параллельного выполнения, и возникающие в связи с этим сложности, видимость, целостность, и тд concurrency напрямую не зависит от количества ядер, а оно имеет место, когда 2+ потока обращаются к один и тем же данным (ресурсам). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.04.2014, 13:07 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
no56892DEVcoach, А как Вы "паритесь с когерентностью кэшэй"Так же, как и остальные - через acquire/release :-) no56892и что такое кэширование в регистрах?Оптимизации JITa. Сделайте следующее: Код: java 1. 2. 3. 4. 5. 6. 7. Через некоторое время (напр. через секунду) из другого потока: Код: java 1. 2. Thread 1 у вас не остановится. Потому что он уже не читает эту переменную ни из памяти, ни из кэша. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.04.2014, 14:45 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
DEVcoachno56892DEVcoach, А как Вы "паритесь с когерентностью кэшэй"Так же, как и остальные - через acquire/release :-) no56892и что такое кэширование в регистрах?Оптимизации JITa. Сделайте следующее: Код: java 1. 2. 3. 4. 5. 6. 7. Через некоторое время (напр. через секунду) из другого потока: Код: java 1. 2. Thread 1 у вас не остановится. Потому что он уже не читает эту переменную ни из памяти, ни из кэша. Вы шутите что-ли? : ) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.04.2014, 15:12 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
no56892Вы шутите что-ли? : )В чем именно? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.04.2014, 15:31 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
no56892concurrency напрямую не зависит от количества ядер, а оно имеет место, когда 2+ потока обращаются к один и тем же данным (ресурсам). Молодец, сразу видно что прочитал первый ответ в этой теме ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.04.2014, 15:35 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
DEVcoachno56892Вы шутите что-ли? : )В чем именно? Ну в том, что Ваш пример работает как и надо, т.е. полностью противоположно тому, что Вы написали. И, если есть, можно еще парочку примеров по управлению кэшем процессора из джавы. авторМолодец, сразу видно что прочитал первый ответ в этой теме Пропустил. Но, кстати в 4м Вашем же ответе все-таки уже не так однозначно как в первом, даже наоборот... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.04.2014, 15:55 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
no56892Ну в том, что Ваш пример работает как и надо, т.е. полностью противоположно тому, что Вы написали. И, если есть, можно еще парочку примеров по управлению кэшем процессора из джавы.Ну вы бы меньше упражнялись в умении язвить, а больше писали по сути :-) Кэшами из Java не управляют. Из Java управляют видимостью изменений, используя acquire/release семантику. А эта семантика, в свою очередь: 1) Накладывает ограничения на оптимизации JIT. 2) Порождает барьеры памяти, которые приводят к синхронизации кэшей по определнным правилам. Это и есть, как вы выразились "управление кэшами из Java". Ну а про пример кода, запустите вот это: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.04.2014, 16:05 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
В данном случае - "проделки JIT", если чуть изменить цикл, то всё работает: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.04.2014, 16:28 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Basil A. SidorovВ данном случае - "проделки JIT оптимизатора" ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.04.2014, 16:29 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Basil A. Sidorov// disable loop unrolling transformation to while(true);Что-то плохо соображаю. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.04.2014, 16:33 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Basil A. SidorovВ данном случае - "проделки JIT", если чуть изменить цикл, то всё работаетнемножко усложним код: Код: 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. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. Из него мы видим, что цикл никуда не делся, так как control постоянно изменяется. Однако изменения мы не видим даже через Unsafe. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.04.2014, 16:37 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Basil A. SidorovЧто-то плохо соображаю.Контрольное чтение через Unsafe в s0 показывает, что поток не видит изменения значения, независимо от того, что там с условием цикла. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.04.2014, 16:41 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Вот, что yield животворящий делает: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.04.2014, 16:48 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Я бы сказал, что махинации с многопоточностью опасны не только из-за неопределённостью с процами, но и зависимостью от планировщиков операционных систем. Так что - ну их нах. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.04.2014, 16:54 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
DEVcoachBasil A. SidorovЧто-то плохо соображаю.Контрольное чтение через Unsafe в s0 показывает, что поток не видит изменения значения, ... Та ну? Код: 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. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. PS. А зачем делать бесконечные циклы без sleep(1)? У вас же загрука ЦП 100% тогда ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.04.2014, 17:03 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
no56892PS. А зачем делать бесконечные циклы без sleep(1)? У вас же загрука ЦП 100% тогдаА зачем замедлять работу программы? Дали шанс выполниться другим потокам - и ладушки. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.04.2014, 17:07 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
no56892 , Вы сути не уловили. Цикл здесь стоит для того, что бы показать, что второй поток не видит изменений первого неограниченно долгое время. Как вы можете объяснить причину этого? Почему я читаю переменную вновь и вновь, но не вижу в ней 1? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.04.2014, 17:08 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
DEVcoachBasil A. SidorovЧто-то плохо соображаю.Контрольное чтение через Unsafe в s0 показывает, что поток не видит изменения значения, независимо от того, что там с условием цикла. Теперь осталось обьяснить почему изменения control в одном потоке видны в другом, a s нет, даже есть поставить s++ во второй цикл, ведь s и control ничем не отличаются, за исключением s в условии цикла. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.04.2014, 17:11 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Чуть модифицировал: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.04.2014, 17:24 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Ну, давайте я попробую объяснить! Мне ж ещё по собеседованиям ходить.. ))) Multithreading - параллельное, или псевдопараллельное (если всего один процессор) выполнение разного или одинакового кода в потоках операционной системы. Потоки отличаются от процессов тем, что выполняются в пределах одного адресного пространства памяти, выделенного на процесс. Concurrency - один из способов синхронизации работы потоков, для согласования работы с общими данными, к которым обращается код из потоков. Вообще, весь этот способ стал актуальным с появлением многопроцессорных машин, а возможен стал благодаря появлению, сначала на RISC-овых процессорах, затем на x86 (кажется начиная с 586, или иначе "пентиум"), команды процессора casa и cmpxchg соответственно - или иначе CAS (compare-and-swap). Это атомарная операция. Атомарность гарантируется тем, что после считывания данных из ячейки памяти не освобождается шина данных, а сначала происходит сравнение, изменилось ли содержимое ячейки памяти. Другой способ обеспечить эксклюзивный доступ к общей памяти - synchronizing - основан на использовании мьютексов операционной системы, и заключается фактически к установке последовательного, поочередного выполнения участков синхронизированного кода. Когда код входит в синхронизированный блок кода, он проверяет мьютекс, и если он установлен, то ждет освобождения. На "несильно параллельных" многопоточных приложениях можно обеспечить эксклюзивный доступ к данным, и избежать ситуаций гонки, с помощью объявления совместно используемых переменных с ключевым словом volatile - в ряде случаев этого может оказаться достаточно. Часто используется совместно с синхронизацией. Объявление переменной с ключевым словом volatile гарантирует, что при модификации данных, значение будет записываться непосредственно в память, а не в кэш. Вот вкратце.. Вопросы? ))) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 09:53 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
mesier , Откровенно говоря, буквально каждое предложение неверно :-) Попозже отвечу, когда время будет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 09:58 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
DEVcoach, ой ли? Может это вы неправильно понимаете что-то? ))) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 10:18 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
mesierMultithreading - параллельное, или псевдопараллельное (если всего один процессор) выполнение разного или одинакового кода в потоках операционной системы. Потоки отличаются от процессов тем, что выполняются в пределах одного адресного пространства памяти, выделенного на процесс.Да. mesierConcurrency - один из способов синхронизации работы потоков, для согласования работы с общими данными, к которым обращается код из потоков.Нет. Канкарренси - это общение потоков в целом. Она не предполагает обязательную согласованность данных. Например, вы можете встретить намеренную несогласованность данных (data races) в классах java.util.concurrent (AbstractQueuedSynchronizer, ConcurrentHashMap, etc.). Но наличие этих несогласованностей не делает этот код "не конкурентным". Он еще какой конкурентный :-) mesierВообще, весь этот способ стал актуальным с появлением многопроцессорных машинНет. Если говорить конкретно про проблемы согласованности данных, то они возникают и на однопроцессорных машинах благодаря оптимизациям JIT-компиляторов. Так что суди о актуальности этой проблемы по количеству процессоров - неверно. mesierВообще, весь этот способ стал актуальным с появлением многопроцессорных машин, а возможен стал благодаря появлению, сначала на RISC-овых процессорах, затем на x86 (кажется начиная с 586, или иначе "пентиум"), команды процессора casa и cmpxchg соответственно - или иначе CAS (compare-and-swap). Это атомарная операция. Атомарность гарантируется тем, что после считывания данных из ячейки памяти не освобождается шина данных, а сначала происходит сравнение, изменилось ли содержимое ячейки памяти.Нет. Разграничивать работу кода можно и без атомарных операций. Например, см. алгоритм Петерсона, для его корректной работы на современных процессорах достаточно обычного volatile. Более того, не все арзитектуры имеют CAS в принципе. На некоторых реализован другой подход - LLSC, обладающий своими преимуществами. Например, отсутсвием ABA-проблемы. В любом случае, псиать конкурентных код можно и без CASов. mesierДругой способ обеспечить эксклюзивный доступ к общей памяти - synchronizing - основан на использовании мьютексов операционной системы, и заключается фактически к установке последовательного, поочередного выполнения участков синхронизированного кода. Когда код входит в синхронизированный блок кода, он проверяет мьютекс, и если он установлен, то ждет освобождения.Если вы про ключевое слово synchornized, то неверно. Прежде, чем Java обратится к ОС за помощью она предпримет огромное количество действий, что бы этого избежать. Почитайте про thin и fat мониторы, и про biasing. Именно факт того, что в отсутствие contention synchronized не лезет в ОС делает его самым быстрым решением среди всех остальных других. А в присутствии contention он начинает проигрывать ReentrantLock. mesierНа "несильно параллельных" многопоточных приложениях можно обеспечить эксклюзивный доступ к данным, и избежать ситуаций гонки, с помощью объявления совместно используемых переменных с ключевым словом volatile - в ряде случаев этого может оказаться достаточно.Нет. volatile не обеспечивает эксклюизвный доступ к памяти. Она лишь обеспечивает видимость изменений между потоками с помощью барьеров памяти. Таким образом, volatile синхронизирует состояние памяти между потоками, но не синхронизирует порядок доступа к памяти этими потоками. mesierОбъявление переменной с ключевым словом volatile гарантирует, что при модификации данных, значение будет записываться непосредственно в память, а не в кэш.Нет, об этом я уже писал выше. volatile никак не влияет на расположение объектов в кэше. Кэшируется абсолютно все. volatile накладывет ограничение на то, какие оптимизации можно проводить с переменной. Например, как я уже писал выше, ее нельзя кэшировать в регистре. Нельзя игнорировать ее чтения. И т.д.. А JIT очень любит заниматься такой ерундой :-) Поэтому, volatile чтение медленнее обычного чтения не потому, что "переменной нет в кэше, и ее долго читать из памяти". Она есть в кэше. А потому, что JIT не имеет права применять к ней свои оптимизации. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 10:47 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
DEVcoach, Тогда и про control и s обьясните, в чем отличие. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 10:52 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
DEVcoach, ну, теперь я вижу, что "на верхнем уровне абстракции" я всё-таки правильно рассказал. Вам просто до%%%ться захотелось.. )) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 11:00 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
0FDТогда и про control и s обьясните, в чем отличие.Мой ответ такой - я не знаю, почему второй поток не видит s = 1 :-) Самый лучший способ достоверно это узнать - обратиться к Шипилеву/Куксенко/Иванову/Дагу. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 11:03 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
mesierDEVcoach, ну, теперь я вижу, что "на верхнем уровне абстракции" я всё-таки правильно рассказал. Вам просто до%%%ться захотелось.. ))Ну если: 1) Сказать, что volatile не кэшируются, хотя они кэшируются; 2) Сказать, что volatile обеспечивает эксклюзивный доступ к данным, хотя она не делает этого; 3) Сказать, что конкарренси возможна только при наличии CAS, хотя это не так; и т.д. это по-вашему "до@баться к мелочам", то пусть будет так :-) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 11:06 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
DEVcoach0FDТогда и про control и s обьясните, в чем отличие.Мой ответ такой - я не знаю, почему второй поток не видит s = 1 :-) Самый лучший способ достоверно это узнать - обратиться к Шипилеву/Куксенко/Иванову/Дагу. Про s=1 понятно, я про control почему изменения control в одном потоке, видны другому, в отличии от s. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 11:10 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
DEVcoachmesierDEVcoach, ну, теперь я вижу, что "на верхнем уровне абстракции" я всё-таки правильно рассказал. Вам просто до%%%ться захотелось.. ))Ну если: 1) Сказать, что volatile не кэшируются, хотя они кэшируются; 2) Сказать, что volatile обеспечивает эксклюзивный доступ к данным, хотя она не делает этого; 3) Сказать, что конкарренси возможна только при наличии CAS, хотя это не так; и т.д. это по-вашему "до@баться к мелочам", то пусть будет так :-) Именно так, дои%%ться!. Я объяснил "на байтах" зачем нужен Concurrency, и очень кратко его основы, а не "только при наличии CAS". А вы ТСу хоть чем-нибудь помогли или только голову заморочили? Кстати, ещё я не говорил слов "только" и "к мелочам", читайте, пожалуйста, внимательнее. Человек вообще спросил о базовых понятиях.. А вы ему про Biased Locking.. ))) Разберётся, когда понадобится. Ибо "Я слышу, и забываю. Я вижу и запоминаю. Я делаю и понимаю", как-то так.. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 11:31 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
mesierDEVcoachпропущено... Ну если: 1) Сказать, что volatile не кэшируются, хотя они кэшируются; 2) Сказать, что volatile обеспечивает эксклюзивный доступ к данным, хотя она не делает этого; 3) Сказать, что конкарренси возможна только при наличии CAS, хотя это не так; и т.д. это по-вашему "до@баться к мелочам", то пусть будет так :-) Именно так, дои%%ться!. Я объяснил "на байтах" зачем нужен Concurrency, и очень кратко его основы, а не "только при наличии CAS". А вы ТСу хоть чем-нибудь помогли или только голову заморочили? Кстати, ещё я не говорил слов "только" и "к мелочам", читайте, пожалуйста, внимательнее. Человек вообще спросил о базовых понятиях.. А вы ему про Biased Locking.. ))) Разберётся, когда понадобится. Ибо "Я слышу, и забываю. Я вижу и запоминаю. Я делаю и понимаю", как-то так.. В этот раз соглашусь со свеномом, многопоточность сложная тема, и именно в деталях и терминах кроется дьявол. Так как примногопоточном программировании ошибку допустить проще простого, как раз таки понимание этих деталей и рулит. Не буду утверждать что я сам гуру, но множество приведенных вами неточностей позволяет сделать вывод про уровень ваших знаний, да, я бы взял вас в команду писать код, который просто работает в разных потоках, но я бы не взял вас в команду по написанию чего-то нового и нешаблонного(пока что). Вообще многопоточность такая штука, в которой просто необходима практика, практика и еще раз практика, а лучше всего пяток пофикшенных гейзенбагов :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 12:04 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
mesierВообще, весь этот способ стал актуальным с появлением многопроцессорных машин, а возможен стал благодаря появлению, сначала на RISC-овых процессорах, затем на x86 (кажется начиная с 586, или иначе "пентиум"), команды процессора casa и cmpxchg соответственно - или иначе CAS (compare-and-swap). Вообще-то мгопоточность программировали ещё на 8086 процессоре (даже не 80186 и тем более задолго до появления 80286). CAS-операций в 8086 как известно нет. Как же они делали это? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 12:15 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
0FDПро s=1 понятно, я про control почему изменения control в одном потоке, видны другому, в отличии от s.x86 достаточно консервативна в возможных реордерингах на железном уровне: TSO. Поэтому по-хорошему за редким ислключением все должны видеть всех. Поэтому я склонен винить в "невидимости" s JIT, а не железо. Судя по всему, он не посчитал нужным записать новое значение s в память. Но это только догадка. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 12:15 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
DEVcoach, Пришлось читать jls Если добавить System.out.println : Код: java 1. 2. 3. 4. читается s=1, цикл заканчивается Получается System.out.println является Synchronization actions которое заставляет читать s=1, такое Synchronization actions заставляет читать counter в другом потоке. Первым Synchronization actions является Thread.start, и во второй поток считывается s=0 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 12:17 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
DEVcoachmesierНа "несильно параллельных" многопоточных приложениях можно обеспечить эксклюзивный доступ к данным, и избежать ситуаций гонки, с помощью объявления совместно используемых переменных с ключевым словом volatile - в ряде случаев этого может оказаться достаточно.Нет. volatile не обеспечивает эксклюизвный доступ к памяти. Она лишь обеспечивает видимость изменений между потоками с помощью барьеров памяти. Таким образом, volatile синхронизирует состояние памяти между потоками, но не синхронизирует порядок доступа к памяти этими потоками. По-моему mesier имеет ввиду, что операция записи значения в volatile переменную гарантировано атомарная (например запись в не-volatile поле типа long не обязательно атомарна, т.е. возможна ситуация, что другой поток увидит наполовину старое/наполовину изменённое значение) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 12:23 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
0FDПолучается System.out.println является Synchronization actions Несогласен с формулировкой, просто JIT выключает свои оптимизации, потому что видит что считанная переменная используется далее. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 12:26 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
забыл ник0FDПолучается System.out.println является Synchronization actions Несогласен с формулировкой, просто JIT выключает свои оптимизации, потому что видит что считанная переменная используется далее. Да и без sysout , s используется далее Код: java 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 12:31 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
0FDПолучается System.out.println является Synchronization actions которое заставляет читать s=1, такое Synchronization actions заставляет читать counter в другом потоке. Первым Synchronization actions является Thread.start, и во второй поток считывается s=0Нет. Вы сейчас пытаетесь объяснить это, основываясь на ваших знаниях работы Java. Но вы не учитываете то, что много чего еще не знаете. Вернее, если быть точным, вы пытаетесь подогнять ваши знания под наблюдаемое поведение. Так лучше не делать. sout не является synchronization action. Но это как минимум системный вызов, который обращается к ядру операционки, порождает context switch, и т.д.. В процессе этой сложной последовательности действий каким-то образом данные между потоками всетаки синхронизируются. Но почему это происходит - большой вопрос. Поэтому нельзя сказать, что sout это synchronization action. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 12:38 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
DEVcoach0FDПолучается System.out.println является Synchronization actions которое заставляет читать s=1, такое Synchronization actions заставляет читать counter в другом потоке. Первым Synchronization actions является Thread.start, и во второй поток считывается s=0Нет. Вы сейчас пытаетесь объяснить это, основываясь на ваших знаниях работы Java. Но вы не учитываете то, что много чего еще не знаете. Вернее, если быть точным, вы пытаетесь подогнять ваши знания под наблюдаемое поведение. Так лучше не делать. sout не является synchronization action. Но это как минимум системный вызов, который обращается к ядру операционки, порождает context switch, и т.д.. В процессе этой сложной последовательности действий каким-то образом данные между потоками всетаки синхронизируются. Но почему это происходит - большой вопрос. Поэтому нельзя сказать, что sout это synchronization action. Это Вы хорошо написали о моих знаниях и наблюдениях. Посмотрите PrintStream.println(тот же sysout) Код: java 1. 2. 3. 4. 5. 6. и jls 17.4.2 Actions Synchronization actions, which are: Volatile read. A volatile read of a variable. Volatile write. A volatile write of a variable. Lock. Locking a monitor <------------------------------- Unlock. Unlocking a monitor. The (synthetic) first and last action of a thread Actions that start a thread or detect that a thread has terminated, as described in §17.4.4. и после этого System.out.println не Synchronization actions? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 12:50 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
0FD , Вы меня неправильно поняли :-) Под "много чего не знаете", я имел ввиду в первую очередь внутреннее устройство операционки, железа, и прочих низкоуровневых вещей. Говоря "вы много чего не знаете", я не претендую на то, что я это знаю. Вы привели в пример sout, и смогли найти этому объяснение. Отлично. Но во-первых, это не полное объяснение, т.к. с точки зрения JMM в этом случае есть acquire в читающем потоке, но нет release в пишущем. Во-вторых, есть масса других способ заставить этот поток увидеть s=1. Например, как уже приводили выше пример, с помощью Thread.yield(). Как вы объясните, что видимость появляется в этом случае? Это нативный метод, к synchronization action не относится ... а видимость дает? Наконец, к synchronization action относят только то, что указано в JMM, базовые кирпичики. Все, что свыше - это не новые sync actions, а лишь надстройки над имеющимися. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 14:53 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
DEVcoach , Кстати, Вы выдвигали версию о том, что это можно объяснить якобы "кэширванием в регистрах", дак вот, попробуйте затестить Ваш же пример с 17 переменными (целочисленных регистров AMD64 - 16). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 15:06 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
no56892 DEVcoach , Кстати, Вы выдвигали версию о том, что это можно объяснить якобы "кэширванием в регистрах", дак вот, попробуйте затестить Ваш же пример с 17 переменными (целочисленных регистров AMD64 - 16).Ну напишите :-) А смысл этих мытарств в чем? Может это регистры, может JIT закэшировал значение в стэке, и не трогает хип. Может быть еще что-то. Прикладной ценности эти копания не имеют. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 15:15 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
DEVcoachВо-вторых, есть масса других способ заставить этот поток увидеть s=1. Например, как уже приводили выше пример, с помощью Thread.yield(). Как вы объясните, что видимость появляется в этом случае? Это нативный метод, к synchronization action не относится ... а видимость дает? Не только yield, но и со sleep. Хотя jls 17.9 Sleep and Yield ... It is important to note that neither Thread.sleep nor Thread.yield have any synchronization semantics. In particular, the compiler does not have to flush writes cached in registers out to shared memory before a call to Thread.sleep or Thread.yield, nor does the compiler have to reload values cached in registers after a call to Thread.sleep or Thread.yield. ... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 15:35 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
For AllВообще-то мгопоточность программировали ещё на 8086 процессоре (даже не 80186 и тем более задолго до появления 80286). CAS-операций в 8086 как известно нет. Как же они делали это?Насколько я помню, префикс lock был изначально. Более следующие процессоры просто ограничили его использование. Плюс, Intel изначально реализовала "блокировку прерываний" для команд, меняющих SP. Именно для того, чтобы гарантировать атомарное переключение стека. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 18:53 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Basil A. SidorovFor AllВообще-то мгопоточность программировали ещё на 8086 процессоре (даже не 80186 и тем более задолго до появления 80286). CAS-операций в 8086 как известно нет. Как же они делали это?Насколько я помню, префикс lock был изначально. Более следующие процессоры просто ограничили его использование. Плюс, Intel изначально реализовала "блокировку прерываний" для команд, меняющих SP. Именно для того, чтобы гарантировать атомарное переключение стека. Насколько я помню, на 8086 многопоточность делали без использования "блокировки прерываний". Тем не менее работало. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 19:20 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
For AllНасколько я помню, на 8086 многопоточность делали без использования "блокировки прерываний"Это вы так думаете. Системный таймер (мегагерц с копейками поделённый на 64к) мог тикнуть в любое времяТем не менее работало.Оно потому и работало, что национальные особенности записи в SP обеспечивали беспроблемное переключение стека, а lock гарантировал работу семафоров. Если, конечно, они использовались. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 19:29 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
забыл ник В этот раз соглашусь со свеномом, многопоточность сложная тема, и именно в деталях и терминах кроется дьявол. Так как примногопоточном программировании ошибку допустить проще простого, как раз таки понимание этих деталей и рулит. Не буду утверждать что я сам гуру, но множество приведенных вами неточностей позволяет сделать вывод про уровень ваших знаний, да, я бы взял вас в команду писать код, который просто работает в разных потоках, но я бы не взял вас в команду по написанию чего-то нового и нешаблонного(пока что). Вообще многопоточность такая штука, в которой просто необходима практика, практика и еще раз практика, а лучше всего пяток пофикшенных гейзенбагов :) Именно так - практика! И как раз практики-то с многопоточностью у меня нет, и именно поэтому забылись детали теории (неиспользуемые знания забываются). Таки куда приходить собеседоваться на позицию "писать код, который просто работает" ? )) Удалёнку рассматриваете? Я как раз сейчас в поиске работы.. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2014, 21:29 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Basil A. SidorovFor AllНасколько я помню, на 8086 многопоточность делали без использования "блокировки прерываний"Это вы так думаете. Системный таймер (мегагерц с копейками поделённый на 64к) мог тикнуть в любое времяИ он тикал - прерывания же не блокировались. И клавиатура тикала по нажатию клавиши, и последовательные порты. Вообще все прерывания срабатывали.Basil A. SidorovТем не менее работало.Оно потому и работало, что национальные особенности записи в SP обеспечивали беспроблемное переключение стека, а lock гарантировал работу семафоров. Если, конечно, они использовались.lock - это блокировка шины на время выполнения команды, актуальна для многопроцессорных/многоядерных систем, и к реализации семафоров на процессоре 8086 (который не яляется многоядерным) не имеет никакого отношения. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.04.2014, 11:57 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
For AllBasil A. Sidorovпропущено... Это вы так думаете. Системный таймер (мегагерц с копейками поделённый на 64к) мог тикнуть в любое времяИ он тикал - прерывания же не блокировались. И клавиатура тикала по нажатию клавиши, и последовательные порты. Вообще все прерывания срабатывали.Basil A. Sidorovпропущено... Оно потому и работало, что национальные особенности записи в SP обеспечивали беспроблемное переключение стека, а lock гарантировал работу семафоров. Если, конечно, они использовались.lock - это блокировка шины на время выполнения команды, актуальна для многопроцессорных/многоядерных систем, и к реализации семафоров на процессоре 8086 (который не яляется многоядерным) не имеет никакого отношения. А что за lock? Разве одной команды? Я всегда думал, что именно чтобы несколько команд выполнить, так сказать транзакцию. А смысл что-то я непойму: на "электрическом уровне" тот-же "mov <something>, 0xadress" implicitly лочит шину или как? А по поводу while(sharedobject.field == 0) { ... } я засабмитил баг в оракл, это ИМХО явный баг. Посмотрим результаты... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.04.2014, 13:37 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
no56892А что за lock? Разве одной команды? Я всегда думал, что именно чтобы несколько команд выполнить, так сказать транзакцию. А смысл что-то я непойму: на "электрическом уровне" тот-же "mov <something>, 0xadress" implicitly лочит шину или как? lock - Assert LOCK# signal for the next instruction. The LOCK prefix causes the LOCK# signal to be asserted during execution of the instruction that follows it. И ещё по поводу шины. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.04.2014, 13:46 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
For Allno56892А что за lock? Разве одной команды? Я всегда думал, что именно чтобы несколько команд выполнить, так сказать транзакцию. А смысл что-то я непойму: на "электрическом уровне" тот-же "mov <something>, 0xadress" implicitly лочит шину или как? lock - Assert LOCK# signal for the next instruction. The LOCK prefix causes the LOCK# signal to be asserted during execution of the instruction that follows it. И ещё по поводу шины. Это если одна шина на память и на IO устройства, а какой смысл в lock если сейчас в в процессоре как минимум одна шина на память и одна на IO ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.04.2014, 13:56 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
no56892А что за lock? Разве одной команды? Я всегда думал, что именно чтобы несколько команд выполнить, так сказать транзакцию. А смысл что-то я непойму: на "электрическом уровне" тот-же "mov <something>, 0xadress" implicitly лочит шину или как?no56892Это если одна шина на память и на IO устройства, а какой смысл в lock если сейчас в в процессоре как минимум одна шина на память и одна на IO ? Например, команда add <something>, 0xadress с точки зрения шины не атомарна - там несколько общений к шине идёт. В многопроцессорной/многоядерной системе разные процессоры/ядра запросто могут обратиться в одну и ту же ячейку памяти (по одной и тоже шине на память) и поломать add друг-другу. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.04.2014, 14:10 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
For Allno56892А что за lock? Разве одной команды? Я всегда думал, что именно чтобы несколько команд выполнить, так сказать транзакцию. А смысл что-то я непойму: на "электрическом уровне" тот-же "mov <something>, 0xadress" implicitly лочит шину или как?no56892Это если одна шина на память и на IO устройства, а какой смысл в lock если сейчас в в процессоре как минимум одна шина на память и одна на IO ? Например, команда add <something>, 0xadress с точки зрения шины не атомарна - там несколько общений к шине идёт. В многопроцессорной/многоядерной системе разные процессоры/ядра запросто могут обратиться в одну и ту же ячейку памяти (по одной и тоже шине на память) и поломать add друг-другу. А, понял. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.04.2014, 14:43 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
забыл никне совсем, multithreading он же возможен и на одном ядре. Это способ разбить задачу на юниты, которые могут, но не обязаны выполняться параллельно. Concurrency же рассматривает как раз вопросы параллельного выполнения, и возникающие в связи с этим сложности, видимость, целостность, и тд В общем-то конкурентные программы могут работать в одном потоке, т.к. конкурентность часто обеспечивается "софтово" -- виртуальной машиной или рантаймом языка и не зависит от потоков/процессов ОС (но может их использовать). Собственно вот. Так что по сути разница между multithreading и concurrency только в реализации, а параллельные вычисления -- совсем другая тема. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.04.2014, 17:05 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
For Alllock - это блокировка шины на время выполнения команды, актуальна для многопроцессорных/многоядерных систем, и к реализации семафоров на процессоре 8086 (который не яляется многоядерным) не имеет никакого отношения.Мопвашуять ... Вы постоянно игнорируете периферийное железо, которое сидело той же самой (общей) шине. Не процессором единым ... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.04.2014, 18:57 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
DEVcoach Сказать, что volatile не кэшируются, хотя они кэшируются; Можно отсюда поподробнее ? Что происходит в тот момент, когда я пытаюсь считать волатильную перменную ? У меня в каждом потоке свое закешированное значение волатильной переменной(непосредственно перед чтением), как они синхронизируются? Как выбирается самое актуальное значение? P.S. я знаю, что volatile write happens-before volatile read ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 11:45 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90Что происходит в тот момент, когда я пытаюсь считать волатильную перменную ? У меня в каждом потоке свое закешированное значение волатильной переменной(непосредственно перед чтением), как они синхронизируются? Как выбирается самое актуальное значение? P.S. я знаю, что volatile write happens-before volatile read Грубо говоря на пальцах это так: переменная - это значение в памяти. Кэш это регистр процессора. Обычную переменную можно не читать из памяти (долго), а прочитать из регистра (быстро). Чтение volatile переменной происходит из памяти. Поэтому там актуальное значение, а не из регистра, где может быть устаревшее. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 11:56 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Blazkowicz, спасибо. Получается, что при каждом изменении волатильной переменной она записывается в локальный кеш потока и в память. P.S. Значит всё-таки "суперкопия" существует. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 12:02 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Blazkowicz, ну и возникает вопрос, зачем вообще тогда кэшировать волатильные переменные? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 12:04 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90Blazkowicz, ну и возникает вопрос, зачем вообще тогда кэшировать волатильные переменные? Зависит от алгоритма. Можешь кешировать. И ты получишь ретроспективноее ее представление. Твой алгоритм будет быстр - но синхронен с "точкой времени в прошлом". По аналогии с курсорами версионных СУБД. Ты не получаешь объективные данные. А ты получаешь данные на момент когда открылся курсор (у тебя - начался твой АЛГОРИТМ). Короче это algorithm depends. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 12:09 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
maytonredwhite90Blazkowicz, ну и возникает вопрос, зачем вообще тогда кэшировать волатильные переменные? Зависит от алгоритма. Можешь кешировать. И ты получишь ретроспективноее ее представление. Твой алгоритм будет быстр - но синхронен с "точкой времени в прошлом". По аналогии с курсорами версионных СУБД. Ты не получаешь объективные данные. А ты получаешь данные на момент когда открылся курсор (у тебя - начался твой АЛГОРИТМ). Короче это algorithm depends. в java я же не могу получить неактуальное значение волатильной переменой. И соответственно алгоритм свой написать не могу. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 12:23 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90в java я же не могу получить неактуальное значение волатильной переменой. И соответственно алгоритм свой написать не могу. Поэтому в Java, чтобы не изучать арихитектуру каждого CPU и особенности JIT компиляции под него, сделана единая JMM, на которую нужно ориентироваться. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 12:25 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Blazkowicz, я наверное непонятно задаю вопрос. Что поменялось бы если бы волатильная переменная не кешировалась бы? Есть хоть один кейс, когда используется значение волатильной переменной из кеша? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 12:27 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90Что поменялось бы если бы волатильная переменная не кешировалась бы? Есть хоть один кейс, когда используется значение волатильной переменной из кеша? С точки зрения Java - разницы никакой нет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 12:31 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90maytonпропущено... Зависит от алгоритма. Можешь кешировать. И ты получишь ретроспективноее ее представление. Твой алгоритм будет быстр - но синхронен с "точкой времени в прошлом". По аналогии с курсорами версионных СУБД. Ты не получаешь объективные данные. А ты получаешь данные на момент когда открылся курсор (у тебя - начался твой АЛГОРИТМ). Короче это algorithm depends. в java я же не могу получить неактуальное значение волатильной переменой. И соответственно алгоритм свой написать не могу. Давай на конкретном случае. Если волатальная переменная - это статистический счётчик который ты просто сыплешь в лог или кидаешь в интерфейсы мониторинга - это одно дело. Если она - это аргумент алгоритма - то тебе придётся "сбрасывать" алгоритм и каждый раз заново выполнять перерасчёт чтобы обеспечить актуальность. Отсюда вопрос. Зачем вообще нужна эта "грязная" (dirty) волатальная перменная. Может лучше переписать код и организовать events которые будут запускать другие потоки с актуальными аргументами? Может с другой стороны подойти к синхронизации? Может volatile это вовсе не тот философский камень который тебе нужен? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 12:31 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90Что поменялось бы если бы волатильная переменная не кешировалась бы?Очевидно увеличится время получения значения из памяти ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 12:45 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Usmanredwhite90Что поменялось бы если бы волатильная переменная не кешировалась бы?Очевидно увеличится время получения значения из памяти Что-то для меня это вообще не очевидно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 12:52 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90Usmanпропущено... Очевидно увеличится время получения значения из памятиЧто-то для меня это вообще не очевидно. http://ru.wikipedia.org/wiki/Кэш_процессора ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 13:04 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Usman, мы ж уже разобрались, что волатильная перменная один хрен будет читаться из памяти. Получается наоборот имеем излишние накладные расходы на запись в кеш, из которого никогда не будем читать эту переменную. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 13:07 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90Что поменялось бы если бы волатильная переменная не кешировалась бы? 16254221 redwhite90волатильная перменная один хрен будет читаться из памятиС этим никто не спорит, другое дело, операция чтения/записи в volatile-переменную будет медленнее. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 13:18 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Usmanredwhite90Что поменялось бы если бы волатильная переменная не кешировалась бы? 16254221 redwhite90волатильная перменная один хрен будет читаться из памятиС этим никто не спорит, другое дело, операция чтения/записи в volatile-переменную будет медленнее. Поясните! В одном случае пишется только в память, в другом в память и в кеш. и вы утверждаете, что писать в память и в кеш быстрее нежели чем просто в кеш. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 13:26 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90, volatile будет медленнее. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 14:28 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
maytonredwhite90, volatile будет медленнее. согласен, но как это коррелируется с Usmanredwhite90Что поменялось бы если бы волатильная переменная не кешировалась бы? Очевидно увеличится время получения значения из памяти вообще не понимаю как это связано. UsmanС этим никто не спорит, другое дело, операция чтения/записи в volatile-переменную будет медленнее. медленне в каком случае ?как сейчас, когда пишется и в кеш и в память или когда пишется только в память? и кстати Blazkowicz , что подразумевается под памятью? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 15:28 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90и кстати Blazkowicz , что подразумевается под памятью? Современные процессоры, намного сложнее устроены. То что я тебе описал, это примерно на уровне Z80 и 8086. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 15:31 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90 , Вынужден констатировать, что все предоставленные вам ответы либо вообще некорректны, либо используют некорректную терминологию, а от того еще больше запутывают. Для понимания работы volatile (и JMM в целом) недостаточно знать Java. Надо понимать архитектуру компьютеру. Постараюсь вам все пояснить, пройдя "снизу вверх". I. Давайте начнем с того, что представим себе, что процессор общается с памятью напрямую. То есть нет никаких регистров, нет никаких кэшей, есть только ядро, память, и шина (суть "провода"), связывающие память и процессор. Когда процессору надо запросить какую-то информацию, он просто говорит памяти "дай мне данные по адресу 100". Просто? Просто. II. К сожалению, упомянутый выше подход не работает. Что такое код программы? Что записано в exe файле, в dll'ке или so'шнике? Это набор инструкций, которые процессор исполняет. В общем случае инструкции выполняются последовательно. Но иногда необходимо перепрыгнуть ряд инструкций, и уйти в другую область кода. Например, когда вы встретили if. Для этого у каждого процессора есть набор соответствующих инструкций (jmp, jne, и т.д..). Но для того, что бы осуществить прыжок, нужно знать адрес той инструкции, на которую надо прыгнуть. Отсюда мы приходим, что каждая инструкция должна иметь адрес, что бы можно было на нее "прыгнуть", так? Окей. а как задать адреса инструкциям? Как записать эти адреса в exe файл? Ну давайте просто последовательно их выдавать, начиная с нуля: 0, 1, 2, 3, ... А потом, когда мы запустим exe-шник, он просто загрузит эти инструкции в память по этим же адресам. То есть инструкция с адресом 100 будет в ячейке памяти 100, 101 в 101, и т.д.. Круто? Не очень, Ведь если вы сначала загрузили программу A, которая заняла адреса 0 ... 100, дошли до инструкции 50, а там вам сказали прыгнуть на 80. А в это время вы запустили программу B, которая перетерла эти инструкции своим кодом. В итоге вы из программы A прыгните на инструкцию 80 ... и начнете выполнять другую программу. Это не круто. Аналогично и с данными, которые нужны программе. Допустим, вы хотите записать по константному адресу какое-то значение, что бы другие участки программы могли ее считать. Вы говорите "запиши эту стрингу по адресу 100500". Потому стартует другая программа, которая ничего не знает о вашей, и просто перетирает ваши данные. Не круто. III. Что бы забороть эти проблемы вводят понятие виртуальных адресов. Когда вы стартуете процесс, ОС выделяет ему какую-то область памяти, к которой имеет доступ он и только он. Например, приложению A дали адреса 0 ... 99, приложению B 100 ... 199. Это круто. Но ведь в exe-шниках обеих программ записаны адреса, начиная с нуля! Как быть? А так, что процессор начинает работать с теми адресами, что записаны в исполняемом файле. Это виртуальные адреса. Но он каким-то образом понимает, что виртуальный адрес 10 для конкретного процесса, это адрес 110 в "реальной памяти" (физический адрес). Отсюда мы приходим к тому, что процессор не может работать с памятью напрямую. Ему как минимум нужен преобразователь адресов. Назовем это устройство "контроллер памяти". Он находится где-то между процессором и физической планкой памяти. И процессор вообще ничего не знает о памяти, установленной внутри вашей системы. Он знает только протокол общения с этим контроллером, и все. IV. Мы знаем, что адреса всегда проходят через этот контроллер. И каждый раз мы получаем виртуальный адрес, каким-то образом превращаем его в физический адрес, и отправляем запрос в память. Потом получаем ответ, делаем обратное преобразование, и отвечаем процессору. А можно ли как-то закэшировать эти пары? Ну, например, если я однажды узнал, что виртуальный адрес 100, а это реальный адрес 995, то я бы хотел запомнить где-то пару (100, 995), что бы потом быстрее делать эти преобразования. Это реально? Конечно реально! Для этого почти на каждом современном процессоре есть так называемый translation lookaside buffer (TLB), который хранит эти пары, ускоряя преобразования виртуаьлных адресов в физические и наоборот. Процессор ничего не знает про этот кэш, он просто спрашивает контроллер. V. Мы так же знаем, что данные так же всегда проходят через этот контроллер, так как процессор не может работать с памятью напрямую. Можем ли мы кэшировать данные так же, как мы кэшируем пары (виртуальный адрес, физический адрес)? Конечно можно! Давайте просто будем сохранять все прошедшие через нас данные куда-то, тем самым ускоряя доступ к ним? Это будет немного медленнее, чем прямая запись в память при первой записи/чтении, но даст нам огромный прирост при последующих доступах к этому же адресу. Мы приходим к первому важному выводу: процессор ничего не знает про кэш. Ни-че-го. Он не может сказать "дайте мне вот это из кэша, а вот это из физической планки". Он просто говорит контроллеру "дай мне такой-то адрес" или "запиши по такому-то адресу", а контроллер уже сам решает, как ему поступить. ВЫВОД 1: Процессор не отличает память и кэш, для него это единая комплексная система. VI. Когда у нас появляется больше, чем одно ядро, мы выделяем каждому ядру по своему кэшу. Но возникает вопрос: а что будет, если два ядра одновременно будут читать/писать по одному адресу? Будут проблемы. Например, в кэше одного процессора может оказаться одно значение, а в кэше другого другое. Или вот другая проблема - что, если в кэше нашего процессора нет значения адреса 100, но он есть в кэше другого процессра? Что нам делать - бежать в основную память, или запросить значение в другом кэше? Быстрее будет запросить у другого кэша. Поэтому, что бы скоординировать действия кэшей разных процессоров, нам надо придумать какой-то протокол их взаимодействия, надо придумать протокол когерентности кэшей . И он был придуман - MESI, и его многочисленные вариации. Когда один процессор записывает что-то по адресу A, то подсистема памяти проверяет кэши всех процессоров, что бы убедиться, что они сотрут (инвалидируют) у себя старое значение, и на следующем чтении смогут вычитать новое значение. Проблема в том, что протоколы когерентности привносят накладные расходы, которые хотелось бы минимизировать. И были придуманы две хитрости: 1) Когда мы делаем запись, то надо сначала инвалидировать значения в других кэшах, а потом уж записать свое значение. Окей, мы запускаем этот процесс ... но не ждем его завершения, а тут же сообщаем процессору "да, все ничтяк, записал", и идем дальше. И пока этот процесс не завершился, новое значение хранится в специальной структуре конкретного ядра - store buffer. Если процессору потребуется еще раз это значение, то мы выдадим ему значение из store buffer. А потом, чуть позже, когда другие кэши ответят, что успешно инвалидировали старое значение, мы уже по-настоящему перенесем это значение из store buffer в кэш. 2) Когда наш кэш просят инвалидировать значение, он может быть занят другими операциями, и ответит на запрос на инвалидацию задержкой. Но эта инвалидация в любом случае рано или поздно произойдет. Поэтому, когда нашему кэшу приходит запрос на инвалидацию, он кладет этот запрос в некую очередь, и сразу же отвечает "да, все ничтяк, инвалидировал", а на самом деле инвалидирует его позднее, когда ему будет это удобно сделать. Эта очередь называется invalidate queue. Эти две хитрости - store buffer и invalidate queue очень здорово ускоряют работу протокола когерентности. Но из-за того, что они по сути асинхронны, кэши разных процессоров могут временно разъезжаться. В итоге то они станут когерентными, но в моменте могут иметь разные значения. Поэтому два одновременных чтения одного и того же адреса на разных ядрах могут вернуть разный результат. Но что сделать, если я хочу, продолжить исполнение только тогда, когда мою запись гарантированно смогут увидеть все другие ядра? Для этого мне надо убедиться, что моя запись ушла из store buffer в кэш. А что сделать, если я хочу вычитать максимально актуальное значение текущей переменной? Для это я должен обработать все текущие invalidate запросы, и только потом попробовать вычитать это значение. Как попросить подсистему памяти сделать это? Для этого у процессоров существуют специальные инструкции (или модификаторы инструкций). Например, для x86 это префикс lock (и другие). А как попросить процессор выполнить эту инструкцию? Ну либо просто ее вызвать на ассемблере, либо же попросить об этом операционную систему, попросив ее вызвать так называемый барьер памяти, который синхронизирует определенным образом состояние кэша текущего процессора с кэшами других. VII Как именно происходит эта синхронизация? Если мне надо убедиться, что запись в кэш завершена, и другие процессору смогут ее увидеть, мне надо дождаться, пока моя запись не уйдет из store buffer в кэш. Но так как записи складываются в store buffer последовательно, к тому моменту, как моя запись уйдет в кэш, в него так же гарантированно уйдут и все предыдущие записи. А что с чтениями? Что бы убедиться, что следующее чтение вернет актуальное значение, мне надо обработать все запросы на инвалидацию из моей invalidate queue. Но это означает, что к моменту чтения актуального значения, я актуализирую не только саму переменную, но и все остальное, что было в моей invalidate queue. А что там могло быть? Как минимум - все то, что было инвалидировано до соответствующей записи из другого процессора. Поэтому, если одни процессор сделал: write A write B [дождаться сброса B] А другой сделал: [дождаться инвалидации всего, что сейчас есть в invalidate queue] read B ... то второй процессор, увидев обновленное B гарантированно увидит и обновленное A! Ничего не напоминает из JMM? Подводим промежуточные итоги: 1) Система кэш-память наразрывна, и процессор видит ее как одно целое. 2) Процессор на может читать/писать в обход кэша. 3) Протоколы когерентности кэшей допускают, что "резъезжание" данных между ядрами в моменте, но гарантирует, что все изменения будут рано или поздно видны всем. VIII Процессор так же любит реордерить инструкции для ускорения их выполнения. Упомянутые "барьеры памяти" предотвращают такие перестановки. IX Теперь перейдем к регистрам. Что это такое? Это небольшая память, находящаяся непосредственно на кристалле процессора. Она может здорово ускорять работу наших программ, так как доступ к данным в регистрах занимает буквально один такт. Для сравнения, доступ к кэшу первого уровня - это около 4 тактов, доступ к кэшу второго уровня - тактов 10-20, и т.д.. Но использовать регистры или нет - это дело разработчика. Теоретически можно работать вообще без регистров общего назначения. То есть оперировать только адресами памяти. И все будет работать. Но медленнее, чем хотелось бы. Поэтому рагистры активно используют. А кто их использует? Вы вот руками дергаете регистры? Нет. И я нет. А кто их использует? Их использует JVM. Она анализирует ваш код и стремиться сделать так, что бы минимизировать объем данных, прокачиваемых между подсистемой памяти и процессором. Для этого в JIT-компиляторе, который генерирует непосредственно машинный код, есть специальных модуль - Register Allocator. Именно он принимает решение как быть с данными - сохранять их в регистрах или нет. Например, увидев, что у вас рядом идут два чтения одной и той же переменной, register allocator может принять решение на первом чтении сохранить данные значение в регистре, и на втором чтении взять его оттуда, а не лезть в систему "память-кэш" снова. X Наконец, JIT может изменять логику вашего кода, что бы минимизировать работу с памятью. Например, если у вас есть цикл while (x == 0) sleep(100); Он может проверить x == 0 один раз, сохранить в регистре значение этого выражения (напр. false), а на следующих итерациях цикла не перечитывать x, а просто брать закэшированный результат. XI Что же мне надо сделать, что бы убедиться, что прочитанное сейчас значение является актуальным? 1) Надо обработать invalidate queue на ядре 2) Надо убедиться, что мое чтение не было переставлено в коде с последующими инструкциями компилятором 3) Надо убедиться, что я не подхвачу старое значение их регистров 4) Надо убедиться, что компилятор не сгенерировал хитровысушенный код, откуда это чтение будет просто напросто выпилено. Как это все сделать за раз? Ответ: volatile. Если мы отметим переменную volatile, то JVM: 1) Не будет сохранять ее в регистрах 2) Не будет оптимизировать код вокруг нее (не будет выпиливать ее чтения, не будет ее переставлять и т.д.) 3) Вокруг ее чтения/записи компилятор добавить специальных инструкций процессора, которые почистят store buffer / invalidate queue кэшей. Обычно это делают через вызов системных функций операционной системы, которая в свою очередь исполнит нужные инструкции процессора. Это и есть volatile, что называется, "на пальцах". Заметьте, volatile кэшируются в кэшах, так же, как и все другие переменные. Кэшировать надо все и всегда, так как читать из память очень дорого. Но для обеспечения правильной видимости, volatile: 1) Форсирует подсистему памяти синхронизировать состояние кэшей. 2) Запрещает JIT-у делать оптимизации на этой переменной. Поэтому, когда говорят, что "volatile медленный", имеют ввиду не то, что "такие переменные не кэшируются", и не то, что "идет сброс в основую память". Ни того, ни другого нет! Все кэшируется, а "сброс в память" лежит на совести подсистемы памяти, а не на volatile. Имеют ввиду то, что мы теряем время на барьерах, которые синхорнизируют кэши, и на оптимизациях, которые JIT мог бы применить, но не стал этого делать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 22:14 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
DEVcoach, спасибо, за подробный ответ и потраченное время. Думаю ешё не раз прочитаю этот текст. Судя по всему, разхожая фраза о том, что volatile не кешируется относится к тому, что volatile не кешируется в регистрах. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 13:23 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
DEVcoach, Поэтому, когда говорят, что "volatile медленный", имеют ввиду не то, что "такие переменные не кэшируются", и не то, что "идет сброс в основую память". Ни того, ни другого нет! Все кэшируется, а "сброс в память" лежит на совести подсистемы памяти, а не на volatile. Имеют ввиду то, что мы теряем время на барьерах, которые синхорнизируют кэши, и на оптимизациях, которые JIT мог бы применить, но не стал этого делать. Большое вам спасибо за развернутый ответ. Это как раз то что я долго хотел сформулировать. Но в рамках действующего форума лучше не писать так много текста. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 14:40 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
DEVcoach, DEVcoachНазовем это устройство "контроллер памяти". Он находится где-то между процессором и физической планкой памяти. И процессор вообще ничего не знает о памяти, установленной внутри вашей системы. Он знает только протокол общения с этим контроллером, и все. В этом предложении под процессором понимаетс одно ядро или именно процессор ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 15:22 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90В этом предложении под процессором понимается одно ядро или именно процессор ?Ядро. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 15:49 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
cdtyjv, я тут вооружился бумагой и ручкой и попытался всё это нарисовать) У меня что-то похожее получилсь: я не очень понимаю как контроллер памяти ядра один узнает о существовании переменной в кеше ядра 2. Какая сущность за это отвечает? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 17:00 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90, контроллер не знает ни о каких переменных. Он видит операции с памятью. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 17:24 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
maytonredwhite90, контроллер не знает ни о каких переменных. Он видит операции с памятью. что конкретно он видит? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 17:26 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90 , В целом вы все правильно нарисовали, за исключением связей между invalidate queue и store buffer - их нет. Между кешами есть шина данных. Когда кэш хочет, например, инвалидировать значение в других кэшах, он отправляет соответствующий запрос в шину, другие кэши его подхватывают, и выполняют инвалидацию. Это называется snooping . Аналогично и с чтением - если вы не находите данные у себя в кэше, вы посылаете запрос в шину. Кэши подхватывают этот запрос, проверяют, есть ли этот адрес у них. Если есть - они выдают его обратно в шину, а запрос в память отменяют. Это уже слишком низкоуровневые дебри. Если хотите в них въехать, то читайте документацию к конкретным процессорам. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 17:35 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Нужно спуститься на несколько уровней ниже Java. Скачай любую книжку по Ассемблеру для Intel x86/x64 Есть класс команд (TRANSFER) осуществляющий операции с памятью. Например Код: plaintext 1. в случае когда dest или source являются адресом пишет или читает атомарную сущность из памяти в регистр или наоборот. Косвенно из сегмента кода, стека постоянно идёт вычитка и запись другими командами типа PUSH/POP/CALL. Вобщем чтива там - непочатый край. Разберись основательно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 17:45 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
cdtyjv redwhite90 , В целом вы все правильно нарисовали, за исключением связей между invalidate queue и store buffer - их нет. Между кешами есть шина данных. Когда кэш хочет, например, инвалидировать значение в других кэшах, он отправляет соответствующий запрос в шину, другие кэши его подхватывают, и выполняют инвалидацию. Это называется snooping . Аналогично и с чтением - если вы не находите данные у себя в кэше, вы посылаете запрос в шину. Кэши подхватывают этот запрос, проверяют, есть ли этот адрес у них. Если есть - они выдают его обратно в шину, а запрос в память отменяют. Это уже слишком низкоуровневые дебри. Если хотите в них въехать, то читайте документацию к конкретным процессорам. Я ниже вашего самого информационно ёмкого сообщения спускаться пока не готов) Но до этого уровня понять очень интересно. так и у меня на картинке связей между invalidate queue и store buffer нет. Эти стрелки значат, что одноврменно записываем в store buffer и в invalidate queue наши значения. Ещё обратную стрелку не нарисовал означающую, что когда значение исчезло из invalidate queue и обработалось кешем ядра, надо послать сигнал о том, что что кеш инвалидирован и соответственно из другого ядра из store buffer можно будет сделать flush этого значения в кеш. теперь по этому вопросу redwhite90я не очень понимаю как контроллер памяти ядра один узнает о существовании переменной в кеше ядра 2. Какая сущность за это отвечает? я так понимаю эта сущность это: авторМежду кешами есть шина данных эта самая "шина кешей" DEVcoach Когда кэш хочет, например, инвалидировать значение в других кэшах, он отправляет соответствующий запрос в шину, другие кэши его подхватывают, и выполняют инвалидацию. Это называется snooping. Извиняюсь за занудство, но тут мне кажется важны все детали. ну как минимум по моей картинке инициатором инвалидироваиня кеша выступает контроллер памяти. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 18:55 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Инвалидация кэша основана на том факте, что у логических схем есть три состояния - ноль, единица и "высокоимпедансное". В третьем состоянии схема не влияет на шину, но может читать сигналы, которые выставляют на ней другие участники. Процессор постоянно следит за (общей) шиной адреса и, если обнаруживает адрес, попадающий в его (процессора) кэш - выставляет флаг "строка кэша невалидна", если служебные сигналы показывают, что по адресу делается запись. Этот механизм работает, если кэш использует сквозную запись, т.к. при отложенной записи модификация строк в кэше процессора не сопровождается сигналами на (общих) шинах адреса/данных. Есть ньюансы "ядра одного кристала" и "ядра разных кристалов", но тут я подробностей не знаю. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 19:28 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90Извиняюсь за занудство, но тут мне кажется важны все детали. ну как минимум по моей картинке инициатором инвалидироваиня кеша выступает контроллер памяти.Не важны тут детали, пока вы не начнёте самостоятельно разрабатывать оптимизирующий компилятор или/и системные программы. В языке высокого уровня у вас есть набор примитивов, которыми можно пользоваться вообще не зная, что там происходит в памяти. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 19:31 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Процессор (ядро процессора) - чёрный ящик, у которого "наружу" торчат две шины - адреса и данных. Эти шины - общие и существуют (аппаратно реализованные) механизмы арбитража, позволяющие корректно использовать эти шины в разных режимах передачи. "Хренотень внутри", которую вы нарисовали ... Можете забыть о ней. Никто, кроме самого изготовителя процессоров не знает в точности что и как устроено внутри чёрного ящика. И, что характерно, никому, кроме самого изготовителя этого и не надо знать - всем остальным достаточно "вполне стандартных" примитивов типа "барьер памяти" и "инвалидация кэша". И то и другое может быть гарантировано определёнными машинными командами и порядком их следования в коде. Да, в теории, знание конкретных детали позволит выжать "последний такт", но это сделает вас таким заложником этих деталей, что epic fail можно будет получить на любой мелочи. P.S. Прицепил вашу картинку файлом, т.к., например, у меня rghost блокирован как нерекомендованный сайт. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 20:04 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
"Наивный чукотский юноша". ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 20:19 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Лично у меня, в Seamonkey, ваши "картинки с другого сайта" просто не отображаются. Запустив тыртырнет-сексплорер я могу получить ссылку, но это мало что меняет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 20:24 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Blazkowiczredwhite90Что происходит в тот момент, когда я пытаюсь считать волатильную перменную ? У меня в каждом потоке свое закешированное значение волатильной переменной(непосредственно перед чтением), как они синхронизируются? Как выбирается самое актуальное значение? P.S. я знаю, что volatile write happens-before volatile read Грубо говоря на пальцах это так: переменная - это значение в памяти. Кэш это регистр процессора. Обычную переменную можно не читать из памяти (долго), а прочитать из регистра (быстро). Чтение volatile переменной происходит из памяти. Поэтому там актуальное значение, а не из регистра, где может быть устаревшее. Чуть менее грубо: кроме вышенаписанного, перед записью волатильной переменной из регистра процессора в память, jvm записывает (если есть) все другие регистры в память. А перед чтением волатильной переменной в регистр из памяти, jvm обновляет остальные регистры из памяти. поэтому записанное перед записью в волатил видится после чтения из волатила. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 21:01 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Ну хотя бы не буду теперь чувствовать себя идиотом, когда начинаются холливары про volatile. Причем обычно у отвечающего хватает ответить что то типа "чувак, ты не прав", там все по другому, на вопрос как кто нить кинет ссылку, которую даже сам не читал. Если кто то пытается объяснить своими словами. Его массово заклевывают, мол ты не прав, но доходчиво на общепонятных(понятных спрашивающему) примитивах никто не удосужится. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 21:10 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Лично я не стал бы полагаться на это поведение. Volatile даёт определённые гарантии относительно конкретной переменной. Ладушки, а всё остальное - от лукавого. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 21:11 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Basil A. SidorovЛично я не стал бы полагаться на это поведение. Volatile даёт определённые гарантии относительно конкретной переменной. Ладушки, а всё остальное - от лукавого.Сила volatile как раз и строится на piggibacking: int x = 0; volatile int y = 0; Thread1: x = 1; y = 1; Thread2: if (y == 1) assert x == 1; Это очень мощная фича, которая очень широко применяют в конкурентном программировании. Ничего в ней "лукавого" нет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 21:32 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
И, типа, от порядка объявления-следования ничего не зависит? Совсем-совсем? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 21:36 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
cdtyjv, про piggyback я тоже слышал. http://stackoverflow.com/questions/8769570/volatile-piggyback-is-this-enough-for-visiblity но минус в том, что если кто-то подумает, что это действие над волатильной переменной не нужно больше(не подумав даже о том волатильная она или нет), удалит одну строчку - всё может накрыться) chabapok Чуть менее грубо: кроме вышенаписанного, перед записью волатильной переменной из регистра процессора в память, jvm записывает (если есть) все другие регистры в память. А перед чтением волатильной переменной в регистр из памяти, jvm обновляет остальные регистры из памяти. поэтому записанное перед записью в волатил видится после чтения из волатила. хм, вижу противоречие... то есть волатильная переменная по вашему пишется в регистр процессора? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 21:37 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
DEVcoach, DEVcoachКак это все сделать за раз? Ответ: volatile. Если мы отметим переменную volatile, то JVM: 1) Не будет сохранять ее в регистрах 2) Не будет оптимизировать код вокруг нее (не будет выпиливать ее чтения, не будет ее переставлять и т.д.) 3) Вокруг ее чтения/записи компилятор добавить специальных инструкций процессора, которые почистят store buffer / invalidate queue кэшей. Обычно это делают через вызов системных функций операционной системы, которая в свою очередь исполнит нужные инструкции процессора. Это и есть volatile, что называется, "на пальцах". Заметьте, volatile кэшируются в кэшах, так же, как и все другие переменные. Кэшировать надо все и всегда, так как читать из память очень дорого. Но для обеспечения правильной видимости, volatile: 1) Форсирует подсистему памяти синхронизировать состояние кэшей. 2) Запрещает JIT-у делать оптимизации на этой переменной. а можете по каждому пункту предоставить прувы, а то смотрю мнения расходятся. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 22:09 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Basil A. SidorovИ, типа, от порядка объявления-следования ничего не зависит? Совсем-совсем?Не понял вопрос. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 22:13 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
cdtyjvНе понял вопрос.Переставили местами порядок объявления переменных, порядок следования операторов в тексте программы. Есть класс с кучей переменных. Если одна единственная volatile выключит оптимизацию всего остального, то не пошло бы оно лесом - такое поведение? На каком фрагменте действует volatile? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 22:18 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
говорят, что понять как работает волатайл можно по следующему коду http://hg.openjdk.java.net/icedtea/jdk7/hotspot/file/d9f0ed25f7ed/src/share/vm/opto/memnode.cpp#l2862 кто знает ассемблер -расскажите что там написано) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 22:21 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90а можете по каждому пункту предоставить прувы, а то смотрю мнения расходятся.Ну давайте для большей точности вот так скажем: 1) Не будет сохранять ее в регистрах 2) Не будет оптимизировать код вокруг нее (не будет выпиливать ее чтения, не будет ее переставлять и т.д.) 3) Вокруг ее чтения/записи компилятор добавить специальных инструкций процессора, которые почистят store buffer / invalidate queue кэшей. Обычно это делают через вызов системных функций операционной системы, которая в свою очередь исполнит нужные инструкции процессора. Ибо п.1 - это по сути одна из оптимизаций из п.2. Здесь принципиально то, что каждое чтение волатильной переменной должно сопровождаться ее реальным чтением из подсистемы "кэш-память". А сохраняет ее процессор для каких-то своих нужд в регистры или нет - дело третье. Хочет сохранить - ну пускай сохранит. Например, предположим, что у нас есть следующий код: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. И вы вызываете method1(). Как будет выглядеть assembly? Может быть так: Код: java 1. 2. А может быть вот так: Код: java 1. 2. // Вызвали метод. Первый способ - стандартный, специфицированный подход к вызову функций. Второй способ - более быстрая вариация, так называемый fastcall, так как быстрее сохранить переменную в регистр, чем записывать ее в стэк. Но в обоих случаях была создана копия волатильной переменной. Это страшно? Нет, ведь мы передаем int в метод, а примитивы передаются в методы по значению. То есть у нас просто напросто нет другого варианта, кроме как скопировать волатильную переменную. Но если бы переменная не была волатильной, то во втором случае JVM могла бы попробовать переиспользовать ее из регистра при последующем чтении. А если она волатильна, то такого переиспользования не будет. Так что не циклитесь на регистрах. Это детали. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 22:26 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
questionerговорят, что понять как работает волатайл можно по следующему коду http://hg.openjdk.java.net/icedtea/jdk7/hotspot/file/d9f0ed25f7ed/src/share/vm/opto/memnode.cpp#l2862 кто знает ассемблер -расскажите что там написано)Это кишки компилятора, они вам никак не помогут понять volatile. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 22:29 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Basil A. SidorovПереставили местами порядок объявления переменных, порядок следования операторов в тексте программы. Есть класс с кучей переменных. Если одна единственная volatile выключит оптимизацию всего остального, то не пошло бы оно лесом - такое поведение? На каком фрагменте действует volatile?volatile не выключает "все остальное". Она синхронизирует состояние в момент ее чтения/записи. До/после этого можно оптимизировать все, что угодно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 22:31 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
cdtyjv, вроде пазл сошёлся) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 22:32 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
cdtyjvvolatile не выключает "все остальное". Она синхронизирует состояние в момент ее чтения/записи. До/после этого можно оптимизировать все, что угодно.Я, таки, нашёл How will the JMM change under JSR 133 и понял то, о чём вы говорите. Возражения против использования такого подхода в прикладном коде - остаются: завтра автор (по забывчивости) или кто другой (по незнанию) переставит местами два оператора потому, что это "эстетичнее", а на работу алгоритма в текущем потоке - никак не влияет. И всё - синхронизация с другими потоками разрушена. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 22:53 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
И, кстати, даже без переупорядочивания ... Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. Вроде - всё хорошо. Но а и б "на трубе не сидят" и JIT невозбранно может кешировать их в регистрах. Если такое кэширование произошло до записи "изменчивой" переменной, то её перечитывание из памяти (само по себе) не отменит регистровые копии. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 23:06 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Мой пример - некорректный, но дальше думать, т.к. возражения всё равно остаются. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 23:12 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. Пример идиотский, но суть проблемы, думаю понятна: изменчивость - плохой барьер. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 23:33 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Basil A. Sidorov Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. Пример идиотский, но суть проблемы, думаю понятна: изменчивость - плохой барьер.Ну так давайте будем рассматривать какой-нибудь "хороший" пример, который действительно можно использовать на практике. Вашей претензией является неочевидность. С этим никто и не спорит. Но с другой стороны, никто и не говорит, что этот подход надо использовать в регулярной практике. Piggibacking часто применяют в замысловатых неблокирующих алгоритмах, когда хотят максимально расслабить синхронизацию, и т.д.. Рядовой программист, который может бездумно "переставить две строчки" в такой код не полезет. Для сложных задач - сложный код, для простых - простой. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 23:44 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
cdtyjvВашей претензией является неочевидность. С этим никто и не спорит. Но с другой стороны, никто и не говорит, что этот подход надо использовать в регулярной практикеСтранные вы люди ... Зачем обсуждать (реально) тёмные детали устройства процессора, если всё, что достаточно знать об изменчивости, укладывается вот в это предложение:Fixing the Java Memory ModelThis process guarantees that when a variable is written by one thread during a synchronized block protected by a given monitor and read by another thread during a synchronized block protected by the same monitor, the write to the variable will be visible by the reading thread? Т.е. раньше гарантии видимости распространялись только на саму переменную, теперь - на все предыдущие присваивания. Что улучшает синхронизацию, за счёт незначительной просадки производительности. P.S. А пример мой относился к тому, что JIT имеет полное право модифицировать код до: Код: sql 1. 2. 3. 4. 5. 6. 7. Однопоточная семантика осталась прежней, многопоточная - разрушена. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.07.2014, 00:04 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Basil A. SidorovЗачем обсуждать (реально) тёмные детали устройства процессора, если всё, что достаточно знать об изменчивости, укладывается вот в это предложение:Fixing the Java Memory ModelThis process guarantees that when a variable is written by one thread during a synchronized block protected by a given monitor and read by another thread during a synchronized block protected by the same monitor, the write to the variable will be visible by the reading thread? Т.е. раньше гарантии видимости распространялись только на саму переменную, теперь - на все предыдущие присваивания. Что улучшает синхронизацию, за счёт незначительной просадки производительности.Всего существует два "типа синхронизации": 1) Release semantics - после записи некоторой переменной она становится потенциально видна другим потокам, так же, как и все записи, которые шли до нее. 2) Acquire semantics - после чтения некоторой переменной, все последующие чтения других переменных должны вычитать более новые значения "себя". Все, другого не дано. Предложение, которое вы привели описывает только synchronized. А работает он так: acquire() тело_synzcronized_блока release() volatile работает вот так: запись_volatile_переменной release() acquire() чтение_volatile_переменной Соответственно, все те трюки с piggibacking, которые возможны с volatile, возможны и с synchronized. Вот это работает: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. Thread 2: Код: java 1. 2. 3. 4. 5. 6. 7. 8. Что бы не верить на слово, что оно работает именно так, а понимать почему оно именно так было спроектировано и именно так работает, и надо знать и про JIT, и про store buffer / invalidate queue. Это улучшает понимание протекающих процессов, а от этого еще никому хуже не стало. Basil A. SidorovОднопоточная семантика осталась прежней, многопоточная - разрушена.Ничего не разрушено ... так как в вашем примере многопоточная семантика изначально была некорректной. Нечего разрушать. Предлагаю оставить этот бессмысленный пример, и рассматривать что-то реально применимое. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.07.2014, 00:24 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90chabapok Чуть менее грубо: кроме вышенаписанного, перед записью волатильной переменной из регистра процессора в память, jvm записывает (если есть) все другие регистры в память. А перед чтением волатильной переменной в регистр из памяти, jvm обновляет остальные регистры из памяти. поэтому записанное перед записью в волатил видится после чтения из волатила. хм, вижу противоречие... то есть волатильная переменная по вашему пишется в регистр процессора? Не очень понял контекст вопроса. Но вцелом да: процессору, чтобы выполнить какую-либо операцию над двумя переменными, надо как минимум одну загрухить в регистр, и результат операции оказывается в регистре. Так, чтобы произвести операцию над двумя ячейками памяти и результат записать сразу в память - в х86 такого нет. И даже если где-то и есть, это большая редкость. То есть да, волатил когда-нибудь в регистр пишется, если операции над волатилом есть. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.07.2014, 09:35 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
cdtyjvНапример, предположим, что у нас есть следующий код: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. И вы вызываете method1(). Как будет выглядеть assembly? Может быть так: Код: java 1. 2. А может быть вот так: Код: java 1. 2. // Вызвали метод. Первый способ - стандартный, специфицированный подход к вызову функций. Второй способ - более быстрая вариация, так называемый fastcall, так как быстрее сохранить переменную в регистр, чем записывать ее в стэк. Но в обоих случаях была создана копия волатильной переменной. Это страшно? Нет, ведь мы передаем int в метод, а примитивы передаются в методы по значению. То есть у нас просто напросто нет другого варианта, кроме как скопировать волатильную переменную. Ваш пример ни при чем. В вашем примере чтение волатила происходит однократно - при передаче в функцию. А в функции х уже будет гарантированно непоменян другим потоком, т.к. это уже локальная переменная. Если мы хотим видеть волатильный х, наш "другой вариант": передавать в method2 this и обращаться к полю x обьекта. cdtyjvНо если бы переменная не была волатильной, то во втором случае JVM могла бы попробовать переиспользовать ее из регистра при последующем чтении. А если она волатильна, то такого переиспользования не будет. для конкретно вашего примера - нет. Переиспользование будет, поскольку переменные передаются по значению, а значение не волатильно. Т.е. внутри функции method2 наше "икс" локально, т.е.ни о какой волатильности не может идти речи. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.07.2014, 09:48 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
chabapokВаш пример ни при чем. В вашем примере чтение волатила происходит однократно - при передаче в функцию. А в функции х уже будет гарантированно непоменян другим потоком, т.к. это уже локальная переменная. Если мы хотим видеть волатильный х, наш "другой вариант": передавать в method2 this и обращаться к полю x обьекта.Мой пример - опровержение моего же тезиса о том, что "волатильные переменные не сохраняются в регистрах". Сохраняются. chabapokдля конкретно вашего примера - нет. Переиспользование будет, поскольку переменные передаются по значению, а значение не волатильно. Т.е. внутри функции method2 наше "икс" локально, т.е.ни о какой волатильности не может идти речи.Я имел ввиду следующий сценарий переиспользования: Код: java 1. 2. 3. 4. 5. 6. 7. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.07.2014, 10:17 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
cdtyjvНичего не разрушено ... так как в вашем примере многопоточная семантика изначально была некорректнойПравильно, некорректной. Что плавно подводит к другой мысли: задолго до того, как нас начнут мучать особенности поведения изменчивых переменных - мы должны научиться писАть многопоточный код, который корректен в принципе . Т.е. снова - ну вот нахрена все эти домыслы об устройстве процессора, если к созданию корректного кода это не приближает ни на шаг? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.07.2014, 10:58 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Basil A. Sidorovну вот нахрена все эти домыслы об устройстве процессораДля понимания разницы между данными, которые находятся в основной памяти (актуальные) и в кэше (возможно "устаревшие"). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.07.2014, 06:17 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
UsmanДля понимания разницы между данными, которые находятся в основной памяти (актуальные) и в кэше (возможно "устаревшие").Зачем требуется понимание этой разницы, если простая оптимизация может использовать (регистровую) переменную которая "уже устарела"? Или даже так: зачем требуется объяснять детали устройства аппаратуры, если точность такого объяснения сомнительна? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.07.2014, 06:51 |
|
||
|
|

start [/forum/topic.php?all=1&fid=59&tid=2126936]: |
0ms |
get settings: |
8ms |
get forum list: |
15ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
148ms |
get topic data: |
14ms |
get forum data: |
2ms |
get page messages: |
170ms |
get tp. blocked users: |
2ms |
| others: | 206ms |
| total: | 571ms |

| 0 / 0 |
