Модель памяти Java - кто-то может объяснить это?

cout << "Enter the number: ";
int number;
if (cin >> number)
{
    // throw away the rest of the line 
    char c;
    while (cin.get(c) && c != '\n')
        if (!std::isspace(c))
        {
            std::cerr << "ERROR unexpected character '" << c << "' found\n";
            exit(EXIT_FAILURE);
        }
    cout << "Enter names: ";
    string name;
    // keep getting lines until EOF (or "bad" e.g. error reading redirected file)...
    while (getline(cin, name))
        ...use name...
}
else
{
    std::cerr << "ERROR reading number\n";
    exit(EXIT_FAILURE);
}

В приведенном выше коде этот бит ...

    char c;
    while (cin.get(c) && c != '\n')
        if (!std::isspace(c))
        {
            std::cerr << "ERROR unexpected character '" << c << "' found\n";
            exit(EXIT_FAILURE);
        }

... проверяет остальную строку ввода после того, как номер содержит только пробелы.

Почему бы просто не использовать ignore?

Это довольно многословно, поэтому использование ignore в потоке после >> x является часто рекомендуемым альтернативным способом отбрасывания контента до следующей новой строки, но он рискует выбросить не-whitespace и при этом игнорируя поврежденные данные в файле. Вам может или не все равно, в зависимости от того, доверено ли содержимое файла, насколько важно избегать обработки поврежденных данных и т. Д.

Итак, когда вы будете использовать clear и ignore?

Таким образом, std::cin.clear()std::cin.igore()) для этого не требуется, но полезно для удаления состояния ошибки. Например, если вы хотите дать пользователю много шансов ввести действительный номер.

int x;
while (std::cout << "Enter a number: " &&
       !(std::cin >> x))
{
    if (std::cin.eof())
    {
        std::cerr << "ERROR unexpected EOF\n";
        exit(EXIT_FAILURE);
    }

    std::cin.clear();  // clear bad/fail/eof flags

    // have to ignore non-numeric character that caused cin >> x to
    // fail or there's no chance of it working next time; for "cin" it's
    // common to remove the entire suspect line and re-prompt the user for
    // input.
    std::cin.ignore(std::numeric_limits<std::streamsize>::max());
}

Не может быть проще с skipws или схожими?

Еще одна простая, но наполовину испеченная альтернатива ignore для вашего первоначального требования использует std::skipws, чтобы пропустить любое количество пробелов перед чтением строк ...

if (std::cin >> number >> std::skipws)
{
    while (getline(std::cin, name))
        ...

... но если он вводится как «1E6» (например, какой-то ученый пытается ввести 1 000 000, но C ++ поддерживает эту нотацию для чисел с плавающей запятой ) не согласятся с этим, вы получите number, установленный на 1, и E6 считанные как первое значение name. Отдельно, если у вас есть действительное число, за которым следуют одна или несколько пустых строк, эти строки будут игнорироваться молча.

28
задан Arkadiy 12 December 2008 в 13:35
поделиться

7 ответов

Я не собираюсь пытаться на самом деле ответить на Ваши вопросы здесь - вместо этого я перенаправлю Вас к книге который я видящий рекомендуемый для совета относительно этой темы: Параллелизм Java на практике .

Одно слово предупреждения: если там ответы здесь, ожидают, что довольно многие из них будут неправы. Одна из причин, я не собираюсь отправлять детали, - то, потому что я вполне уверен , я был бы понимать ее превратно в, по крайней мере, некоторых отношениях. Я не имею в виду непочтительности вообще к сообществу, когда я говорю, что возможности всех, кто думает, что они могут ответить на этот вопрос, на самом деле имеющий достаточно суровости для разбираний в нем, является практически нулевым. (Joe Duffy недавно нашел немного моделью памяти.NET, которая была удивлена. Если он может понять его превратно, так могут смертные как мы.)

<час>

я предложу некоторое понимание всего на одном аспекте, потому что это часто неправильно понимается:

существует различие между энергозависимостью и атомарностью. Люди часто думают, что атомарная запись энергозависима (т.е. Вы не должны волноваться о модели памяти, если запись является атомарной). Это не верно.

Энергозависимость о том, будет ли один поток, выполняющий чтение (логически, в исходном коде), "видеть" изменения, внесенные другим потоком.

Атомарность о том, существует ли шанс, что, если изменение замечено, только часть изменения будет замечена.

, Например, возьмите запись в целочисленное поле. Это, как гарантируют, будет атомарным, но не энергозависимым. Это означает это, если мы имеем (запускающийся в foo.x = 0):

Thread 1: foo.x = 257;
Thread 2: int y = foo.x;

для y возможно быть 0 или 257. Это не будет никакое другое значение, (например, 256 или 1) из-за ограничения атомарности. Однако, даже если Вы знаете, что в "стенное время" код в потоке 2 выполняемых после кода в потоке 1, могло быть нечетное кэширование, доступы памяти, "перемещающиеся" и т.д. Создание переменной x энергозависимый зафиксирует это.

я оставлю остальных до настоящих кристально честных экспертов.

33
ответ дан Jon Skeet 14 October 2019 в 10:31
поделиться

Я попытка привычки объяснить эти проблемы здесь, но вместо этого отослать Вас к Brian Goetz превосходная книга по предмету.

книга является "Параллелизмом Java на практике", может быть найден в Amazon или любое другое хорошо отсортированное хранилище для компьютерной литературы.

7
ответ дан Filip Korling 14 October 2019 в 10:31
поделиться
  • не - volatile переменные могут кэшироваться поток локально, таким образом, различные потоки могут видеть различные значения одновременно; volatile предотвращает это ( источник )
  • , записи к переменным 32 битов или меньший, как гарантируют, будут атомарными ( подразумеваемый здесь ); не так для long и double, хотя JVMs на 64 бита, вероятно, реализуют их как атомарные операции
13
ответ дан Michael Borgwardt 14 October 2019 в 10:31
поделиться

Это - хорошая ссылка, которая может дать Вам немного подробно информацию:

http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html

4
ответ дан Yuval Adam 14 October 2019 в 10:31
поделиться

Одно понятие могло бы быть полезным: данные (данная величина) и копии.

, Если Вы объявляете переменную, скажем, байт, это находится где-нибудь в памяти в сегменте данных (примерно говорящий). Существует 8 битов где-нибудь в памяти, посвященной для хранения той информации.

Однако может быть несколько копий тех данных, перемещающихся в Вашей машине. Для различных технических причин, например, локального устройства хранения данных потока, оптимизации компилятора. И если у нас есть несколько копий, они могли бы быть вне синхронизации.

, Таким образом, необходимо всегда иметь в виду это понятие. Это верно не только для полей класса Java, но и для cpp переменных, записи базы данных (рекордные данные состояния копируются в несколько сессий и т.д.). Переменные, их скрытые/видимые копии и тонкие проблемы синхронизации будут вокруг навсегда.

0
ответ дан Karl 14 October 2019 в 10:31
поделиться

Я недавно нашел превосходная статья , которые объясняют энергозависимый как:

Первый, необходимо понять немного что-то о модели памяти Java. Я изо всех сил пытался за годы объяснить его кратко и хорошо. На сегодняшний день лучший способ, которым я могу думать для описания его, состоит в том, если Вы воображаете его этим путем:

  • Каждый поток в Java происходит в отдельном пространстве памяти (это явно неверно, поэтому терпите меня на этом).

  • необходимо использовать специальные механизмы, чтобы гарантировать, что коммуникация происходит между этими потоками, как Вы были бы в системе передачи сообщений.

  • записи Памяти, которые происходят в одном потоке, могут "просочиться через" и быть замечены другим потоком, но это ни в коем случае не гарантируется. Без явной коммуникации Вы не можете гарантировать, какие записи замечены другими потоками, или даже порядком, в котором они замечены.

Java энергозависимый модификатор является примером специального механизма, чтобы гарантировать, что коммуникация происходит между потоками. Когда один поток пишет в энергозависимую переменную, и другой поток видит, что запись, первый поток говорит, что второе обо всем содержании памяти вплоть до него выполнило запись к той энергозависимой переменной.

Дополнительные ссылки: http://jeremymanson.blogspot.com/2008/11/what-volatile-means-in-java.html http://www.javaperformancetuning.com/news/qotm030.shtml

4
ответ дан fgb 14 October 2019 в 10:31
поделиться

Другие ответы выше абсолютно верны в том смысле, что ваш вопрос не для ловушек сердца.

Тем не менее, я понимаю вашу боль из-за того, что вы действительно хотите получить то, что находится под капотом - для этого я хотел бы указать вам на компиляторы миров и предшественников нижнего уровня для java, то есть на ассемблер, C и C ++.

Прочтите о различных видах заграждений («заборов»). Понимание того, что такое барьер памяти и где он необходим, поможет вам интуитивно понять, что делает volatile.

1
ответ дан 28 November 2019 в 02:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: