2015-04-25 5 views
-1

Я часто читал, что вам не нужно беспокоиться о состоянии гонки в javascript, поскольку это однопоточный. Но я считаю, что это из-за характера циклов событий. Javascrit все еще может иметь проблемы с параллелизмом, если у него не было функции «Run-to-completion».Можем ли мы иметь условия гонки в однопоточных сценариях?

Давайте рассмотрим этот фрагмент кода:

1 var pending = []; 

2 document.getElementById("submitBtn").addEventListener(function() { 
3  var val = document.getElementById("textBox").value; 
4  pending.push(val); 
5 }); 

6 setInterval(function() { 
7  processValues(pending); 
8  pending = []; 
9 }, 3000); 

, что предполагаю, не было такой функции в JavaScript «Run-to-completion» и любое событие может быть предварительно опорожнить, чтобы запустить другое событие/код.

Теперь предположим, что строка 7 запускается, и внезапно событие получает предупреждение для обработки события в строке 3. После выполнения строки 3 & 4 предыдущее событие возобновляется из строки 8. Теперь, когда строка 8 выполняется, новая добавленная стоимость в pending будет потеряна, потому что она не обрабатывается функцией processValues, но не находится в массиве pending.

Состояние гонки произошло, хотя оно однопоточное. Итак, неправильно говорить, что javascript не имеет условий гонки, потому что он однопоточный? В частности, это из-за функции Run-to-completion javascript?

EDIT

По-видимому, могут быть условия гонки в JavaScript. То, что я имел в виду, это определенный класс условий гонки, который не возникает из-за однопоточного (или из-за Run-to-completion?) Характера javascript. Например, тот, который я описал выше.

+0

Где вы это читали? Условия гонки являются общими для асинхронного кода. – Jivings

+1

Условия гонки возможны в асинхронных частях javascript, websockets и т. Д. – adeneo

+0

Задумчивый ответ уже предоставлен для этого, если вам интересно: http://stackoverflow.com/questions/21463377/can-we-have- race-conditions-in-a-one-thread-program – brianvaughn

ответ

2

Да, у нас есть условия гонки в однопоточном JavaScript. Просто не так много, как в многопоточном коде (при условии, что вы не используете alert или confirm, ниже).

Вы начали с того, что произнесли «не выполняйте функцию запуска до завершения», а затем описали условие гонки, основанное на этом. Но этого состояния гонки не может быть, потому что, как вы говорите, JavaScript работает с завершением.

Хотя это правда, что есть класс условий гонки, нам не о чем беспокоиться в JavaScript, есть еще много мы, do нужно беспокоиться. Асинхронный код, например, всегда будет иметь потенциал для условий гонки. (Так что это Ajax звонки, сообщения с веб-рабочих и т.д.)

Вот пример ошибки вы видите обычно, что реального мира состояние гонки:

var img = document.createElement('img'); 
img.src = "kittens.png"; 
img.onload = function() { 
    console.log("It loaded"); 
}; 
document.body.appendChild(img); 

Это безопасно, правильно? Неправильно. Просто потому, что JavaScript работает однопоточно, это не значит, что браузер однопоточный. Когда браузер видит img.src = "kittens.png";, если изображение находится в кеше, оно совершенно в пределах его прав, чтобы запустить событие load на этом img: это событие будет искать любые обработчики, а не находить, и поэтому не ставит в очередь любые обратные вызовы, которые будут выполняться после текущий код завершает   —, и мы не видим сообщение «Это загружено».

И хотя это пример на основе браузера, это пример общего долга: Просто потому, что хозяин среда работает один основной JavaScript нить, это не означает, что хозяина окружающей не умножать-резьбовой , и что эта многопоточность может иметь последствия для нашего однопоточного кода.

Это всего лишь один пример. Но это правда, что мы в безопасности от других. Например, если мы изменим код, указанный выше:

var img = document.createElement('img'); 
img.onload = function() { 
    console.log("It loaded"); 
}; 
img.src = "kittens.png"; 
document.body.appendChild(img); 
doSomethingElse(); 

... мы знаем doSomethingElse будут вызываться до "It loaded" прогонов, за исключением некоторых неприятных случаев краев на некоторых браузерах (я смотрю на вас, Mozilla) вокруг функций alert и confirm; bobince covers those in this other answer. (TL; DR) По крайней мере, некоторые версии Firefox будут срабатывать при обратном вызове завершения ajax , ожидая, когда пользователь уволит alert.)

+0

Хороший ответ. Хотя я думаю, что проблема в том, что javascript на самом деле не однопоточный. Если вы посмотрите на простую программу Java, которая не запускает ни темы, ни какие-либо асинхронные методы (на самом деле асинхронный подразумевает многопоточность, я думаю). ТО, что невозможно создать условия гонки, не так ли? – maraca

+0

@maraca: Ну, ** JavaScript **, язык, полностью бесшумен на потоке. Хозяин предоставляет только поточные гарантии. * JavaScript в веб-браузерах * имеет доступ к одному потоку пользовательского интерфейса и количеству пользователей Интернета. Игнорирование веб-работников, основанный на браузере JavaScript, действительно однопоточное, запрещающее проблемы, о которых я упоминал в конце моего ответа, а веб-сотрудники были очень разумно разработаны для использования модели событий сообщений и изоляции работников, чтобы не нарушить это. Аналогично, JavaScript на, скажем, NodeJS, гарантируется одним потоком NodeJS. JavaScript на JVM (Rhino, Nashorn) нет. –

+0

@ T.JCrowder да, это точно моя точка зрения, вы не можете применить это к JavaScript, но это может быть правдой для других языков. – maraca