<script type='text/javascript'>
var lookup = '\n\n\n\n\n\n2 PC Games \n\n\n\n';
lookup = lookup.trim() ;
alert(lookup );
var tttt = 'tttt';
alert((/\b(lookup)\b/g).test(2));
</script>
Трудно сказать, что вы пытаетесь сделать здесь. Какова должна быть переменная tttt
?
В какую строку вы пытаетесь выполнить поиск? Вы пытаетесь найти 2
в строке lookup
? Тогда вам нужно:
/\b2\b/.test(lookup)
Следующее из вашего регулярного выражения создает регулярное выражение, состоящее из границы слова, за которым следует строка "lookup"
(а не значение, содержащееся в переменной lookup
), за которым следует граница слова. Затем он пытается сопоставить это регулярное выражение со строкой "2"
, полученной путем преобразования числа 2
в строку:
(/\b(lookup)\b/g).test(2)
Например, следующие возвраты true
:
(/\b(lookup)\b/g).test("something to lookup somewhere")
Два потока, получая доступ к неатомарной, неохраняемой переменной U.B. Это касается finished
. Вы могли сделать finished
из типа std::atomic<bool>
для фиксации этого.
Моя фиксация:
#include <iostream>
#include <future>
#include <atomic>
static std::atomic<bool> finished = false;
int func()
{
size_t i = 0;
while (!finished)
++i;
return i;
}
int main()
{
auto result=std::async(std::launch::async, func);
std::this_thread::sleep_for(std::chrono::seconds(1));
finished=true;
std::cout<<"result ="<<result.get();
std::cout<<"\nmain thread id="<<std::this_thread::get_id()<<std::endl;
}
Вывод:
result =1023045342
main thread id=140147660588864
Живая Демонстрация на <часе> coliru
Кто-то может думать, что 'Это bool
– вероятно, один бит. Как это может быть неатомарным?' (Я сделал, когда я запустил с многопоточности сам.)
, Но примечание, что отсутствие разрыва не является единственной вещью, которая std::atomic
дает Вам. Это также делает параллельный read+write доступ из нескольких потоков четко определенным, мешая компилятору предположить, что перечитывание переменной будет всегда видеть то же значение.
Создание bool
неосторожный, неатомарный может вызвать дополнительные проблемы:
atomic<bool>
с memory_order_relaxed
хранилище/загрузка работало бы, но где volatile
не будет. Используя энергозависимый для этого был бы UB, даже при том, что он работает на практике над реальными реализациями C++.) Для предотвращения этого для случая компилятор должен быть сказан явно не сделать.
<час>я немного удивлен о развивающемся обсуждении относительно потенциального отношения [1 111] к этой проблеме. Таким образом я хотел бы к потраченному свои два цента:
Ответ Scheff описывает, как исправить Ваш код. Я думал, что включу немного информации, что на самом деле происходит в этом случае.
я скомпилировал Ваш код в [1 115] godbolt с помощью уровня 1 (-O1
) оптимизации. Ваша функция компилирует как так:
func():
cmp BYTE PTR finished[rip], 0
jne .L4
.L5:
jmp .L5
.L4:
mov eax, 0
ret
Так, что происходит здесь? Во-первых, у нас есть сравнение: cmp BYTE PTR finished[rip], 0
- это проверяет, чтобы видеть, ли finished
ложь или нет.
, Если это не ложь (иначе верный) мы должны выйти из цикла на первом показе. Выполненный jne .L4
, который j судьи, когда квалификация n ot e для маркировки .L4
, где значение i
(0
) хранится в регистре для более позднего использования и функциональных возвратов.
, Если это ложь однако, мы перемещаемся в [1 123]
.L5:
jmp .L5
, Это - безусловный переход, для маркировки .L5
, который именно так, оказывается, сама команда перехода.
, Другими словами, поток помещается в бесконечный занятый цикл.
Итак, почему это произошло?
Насколько оптимизатор затронут, потоки за пределами его области. Это предполагает, что другие потоки не читают или пишут переменные одновременно (потому что это было бы гонкой данных UB). Необходимо сказать этому, что это не может оптимизировать доступы далеко. Это - то, где ответ Scheff входит. Я не потружусь повторять его.
, поскольку оптимизатор не сказан, что finished
переменная может потенциально измениться во время выполнения функции, это видит, что finished
не изменяется самой функцией и предполагает, что это постоянно.
оптимизированный код обеспечивает два пути выполнения кода, которые будут следовать из ввода функции с постоянным значением bool; или это выполняет цикл бесконечно, или цикл никогда не выполняется.
в [1 113] компилятор (как ожидалось) не оптимизирует тело цикла и сравнение далеко:
func():
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], 0
.L148:
movzx eax, BYTE PTR finished[rip]
test al, al
jne .L147
add QWORD PTR [rbp-8], 1
jmp .L148
.L147:
mov rax, QWORD PTR [rbp-8]
pop rbp
ret
поэтому функция при неоптимизации действительно работает, отсутствие атомарности здесь обычно является не проблемой, потому что код и тип данных просты. Вероятно, худшим, с которым мы могли столкнуться здесь, является значение [1 114], который выключен одним к тому, чем он должен быть.
А более сложная система со структурами данных, намного более вероятно, приведет к поврежденным данным или неподходящему выполнению.
Ради полноты в кривой обучения; необходимо избегать использования глобальных переменных. Вы сделали хорошее задание, хотя путем создания этого статичным, таким образом, это будет локально для единицы перевода.
Вот пример:
class ST {
public:
int func()
{
size_t i = 0;
while (!finished)
++i;
return i;
}
void setFinished(bool val)
{
finished = val;
}
private:
std::atomic<bool> finished = false;
};
int main()
{
ST st;
auto result=std::async(std::launch::async, &ST::func, std::ref(st));
std::this_thread::sleep_for(std::chrono::seconds(1));
st.setFinished(true);
std::cout<<"result ="<<result.get();
std::cout<<"\nmain thread id="<<std::this_thread::get_id()<<std::endl;
}
Живой на wandbox