Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2008.01.27;
Скачать: CL | DM;

Вниз

Вопрос про многопоточность.   Найти похожие ветки 

 
@!!ex ©   (2007-12-24 18:46) [0]

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


 
oxffff ©   (2007-12-24 18:55) [1]


> @!!ex ©   (24.12.07 18:46)  


А как ты меняешь значения?


 
@!!ex ©   (2007-12-24 18:56) [2]

procedure TKeys.Update;
var
 Index:integer;
begin
 GetKeyboardState(NewKeys);
 for Index:=0 to 255 do
   if NewKeys[Index] shr 7 <> OldKeys[Index] shr 7 then
     Keys[Index]:=NewKeys[Index] shr 7 = 1;

 CopyMemory(@OldKeys[0],@NewKeys[0],256);

end;


Я думаю может работать с отдельным массивом, а потом его копировать в основной?
ТОгда замена каждого жэлемента будет атомарной операцией?


 
oxffff ©   (2007-12-24 18:58) [3]


> @!!ex ©   (24.12.07 18:46)  


Если просто меняешь,то на многопроцессорных машинах потенциально это может стать причиной некорретного поведения.

Решение использование InterlockedExchange


 
oxffff ©   (2007-12-24 19:00) [4]


> @!!ex ©   (24.12.07 18:56) [2]


Открой SDK см. раздел Synchronization

Synchronization and Multiprocessor Issues


 
DiamondShark ©   (2007-12-24 19:02) [5]

Если главный поток только читает, а пишет только один доп. поток, то ничего страшного не произойдёт.


 
oxffff ©   (2007-12-24 19:02) [6]


> @!!ex ©   (24.12.07 18:56) [2]


Решение - это обеспечение когерентности кэшей процессоров.


 
@!!ex ©   (2007-12-24 19:02) [7]

> Если просто меняешь,то на многопроцессорных машинах потенциально
> это может стать причиной некорретного поведения.

тоесть там может читаться в тоже время, когда писаться?


 
oxffff ©   (2007-12-24 19:02) [8]


> DiamondShark ©   (24.12.07 19:02) [5]


Читай мат. часть.


 
@!!ex ©   (2007-12-24 19:04) [9]

AV быть может или нет в данной ситуации?
Или это грозит только некорректностью данных?


 
oxffff ©   (2007-12-24 19:05) [10]


> @!!ex ©   (24.12.07 19:02) [7]


Представление памяти потоков запущенных на разных процессорах будет разным.

Memory Caching

When a processor writes to a memory location, the value is cached to improve performance. Similarly, the processor attempts to satisfy read requests from the cache to improve performance. Furthermore, processors begin to fetch values from memory before they are requested by the application. This can happen as part of speculative execution or due to cache line issues.


 
oxffff ©   (2007-12-24 19:06) [11]


> @!!ex ©   (24.12.07 19:04) [9]


Это грозит только некорретностью данных, которое может привести к AV. :)


 
@!!ex ©   (2007-12-24 19:07) [12]

> [11] oxffff ©   (24.12.07 19:06)

Вобщем я понял. :)

К счастью, нашлось решение, которое убирает необходимость в двух потоках...
УРА! :)))


 
DiamondShark ©   (2007-12-24 19:13) [13]


> oxffff ©   (24.12.07 19:02) [8]
>
> > DiamondShark ©   (24.12.07 19:02) [5]
>
> Читай мат. часть.

Читай условия, попугайчик. А то память у тебя хорошая, а соображения -- ноль.


 
oxffff ©   (2007-12-24 19:16) [14]


> DiamondShark ©   (24.12.07 19:13) [13]


Хавальничек свой прикрыл бы, дружок.
И прочитал бы внимательно сам.

Условия:  один поток пишет ( CopyMemory(@OldKeys[0],@NewKeys[0],256); )
             другой поток читает.


 
@!!ex ©   (2007-12-24 19:20) [15]

> [14] oxffff ©   (24.12.07 19:16)

Не. Общие данные - массив Keys.


 
oxffff ©   (2007-12-24 19:26) [16]


> @!!ex ©   (24.12.07 19:20) [15]


O. :)

Ну разницы особой нет.
Основное, что это не инструкции с lock префиксом.


 
DiamondShark ©   (2007-12-24 19:26) [17]


> oxffff ©   (24.12.07 19:16) [14]

Глупышка. Ты даже не въехал, какой массив совместно используется.


 
oxffff ©   (2007-12-24 19:29) [18]


> DiamondShark ©   (24.12.07 19:26) [17]


Ну не беда. Меня поправили.
И ты даже не понял о чем говорил. Это печальнее. :)


 
DiamondShark ©   (2007-12-24 19:30) [19]


> oxffff ©   (24.12.07 19:26) [16]

В контекст задачи ты тоже не въехал: в то, что элементы массива примитивного типа, в то, какой смысл имеют значения элементов массива.

Ты себе голову цитатами набил -- тебе достаточно.


 
oxffff ©   (2007-12-24 19:32) [20]


> DiamondShark ©   (24.12.07 19:26) [17]


Ну тем не менее я ответил на вопрос автора
Чем грозит такая ситуация
А ты вякяешь без доказательств.

P.S. А твои оскорбления говорят о том, что увы больше ты ничего не знаешь.


 
@!!ex ©   (2007-12-24 19:32) [21]

oxffff, DiamondShark - расслабьтесь.


 
@!!ex ©   (2007-12-24 19:33) [22]

Лучше расскажите, почему не работает?
 GetKeyboardState(NewKeys);
 for Index:=0 to 255 do
   if NewKeys[Index] shr 7 <> OldKeys[Index] shr 7 then
     Keys[Index]:=NewKeys[Index] shr 7 = 1;

 CopyMemory(@OldKeys[0],@NewKeys[0],256);


Вынес в обработку мультимедийного таймера.
TimerID:=timeSetEvent(16,0,@TimerProc,0,TIME_PERIODIC);

Keys всегда содержит false....


 
trubin ©   (2007-12-24 19:34) [23]

To модератор:
на ветку пора замок вешать


 
oxffff ©   (2007-12-24 19:36) [24]


> DiamondShark ©   (24.12.07 19:30) [19]


Я то все понял.
А ты пытаешь съехать сваливая на незначимость Shared Data.
А мои ответы конкретно касаются случая для многопроцессорных машин.

Рекомендую тебе заглянуть в SDK.
Там достаточно хороший пример.


 
oxffff ©   (2007-12-24 19:39) [25]


> @!!ex ©   (24.12.07 19:33) [22]


Я не телепат.


 
@!!ex ©   (2007-12-24 19:40) [26]

> [25] oxffff ©   (24.12.07 19:39)

идей нет?


 
oxffff ©   (2007-12-24 19:40) [27]


> DiamondShark ©   (24.12.07 19:30) [19]


Похоже ты завидуешь.


 
oxffff ©   (2007-12-24 19:42) [28]


> @!!ex ©   (24.12.07 19:40) [26]


Идеи?
Повторяю я не телепат.
Ни точной постановки задачи,  ни твоей реализации нет.


 
DiamondShark ©   (2007-12-24 19:44) [29]


> oxffff ©   (24.12.07 19:40) [27]
>
> > DiamondShark ©   (24.12.07 19:30) [19]
>
>
> Похоже ты завидуешь.

:))))))
Чему? Умению цитировать МСДН? С этим справится не слишком сложный бот, настроеный на ключевые слова.


 
DiamondShark ©   (2007-12-24 19:46) [30]


> @!!ex ©   (24.12.07 19:40) [26]
> > [25] oxffff ©   (24.12.07 19:39)
>
> идей нет?

Просто он ещё не добрался до нужной страницы SDK ;)

А там написано вот что:

GetKeyboardState
An application can call this function to retrieve the current status of all the virtual keys. The status changes as a thread removes keyboard messages from its message queue. The status does not change as keyboard messages are posted to the thread"s message queue, nor does it change as keyboard messages are posted to or retrieved from message queues of other threads. (Exception: Threads that are connected through AttachThreadInput share the same keyboard state.)


 
oxffff ©   (2007-12-24 19:52) [31]


> DiamondShark ©   (24.12.07 19:44) [29]


Слушай, ты что глупый?

Тебе сказали, что представление памяти для потоков запущенных на разных процессорах в один и тот же момент будет разным.
Если ты не понимаешь, что операция установки нового состояния для всего массива не атомарна, то будут dirty Updates.
Которые могут приводить к проблемам в логике даже на однопроцессорной машине.
На многопроцессорной машине ситуация еще хуще. Ты обновил значения, а другой поток не видит обновления.
А если это критично?


 
oxffff ©   (2007-12-24 19:56) [32]


> DiamondShark ©   (24.12.07 19:46) [30]


Ты реально не понимаешь проблемы.
Опять пытаешься съехать.

for Index:=0 to 255 do
  if NewKeys[Index] shr 7 <> OldKeys[Index] shr 7 then
    Keys[Index]:=NewKeys[Index] shr 7 = 1;


Это не атомарная операция.
-> потенциальные проблемы на однопроцессорной машине.
Состояние обновлено частично в момент работы потока чтения.

-> потенциальные проблемы на многопроцессорной машине.
Не видно обновления в потоке чтения, либо видно частично.


 
DiamondShark ©   (2007-12-24 20:11) [33]


> oxffff ©   (24.12.07 19:52) [31]

Это ты глупый. Не видишь разницы между общим правилом и частным случаем.


> Это не атомарная операция.

Конечно. Запись байта -- сильно не атомарная операция. ;)
Я поторопился с оценкой "хорошая память". Ты опять забыл, какой массив общий.


> Состояние обновлено частично в момент работы потока чтения.

Да. Пол-байта записали. ;)


> Не видно обновления в потоке чтения, либо видно частично.

Булеан значение частично -- это у блондинок.

Ты за весь массив целиком боишься? Зря. Прикладные данные в нём такого характера, что это совершенно не критично.


> Опять пытаешься съехать.

Опять твоё воображение.
Ты почему-то решил, что я давал общий ответ, а не в контексте задачи, а потом коварно "съехал".
Но твои церебральные тараканы -- твоя личная проблема.


 
DiamondShark ©   (2007-12-24 20:15) [34]


> Если ты не понимаешь, что операция установки нового состояния
> для всего массива не атомарна

Весь массив никого не волнует.
Вникай в задачу.
Массив здесь только из соображений удобства доступа. А по задаче -- это 256 независимых булевских переменных.


 
@!!ex ©   (2007-12-24 20:16) [35]

> Ни точной постановки задачи,  ни твоей реализации нет.

Да как же нет?
Все реализация здесь...
Нужно получить состояние клавиши...
И оно не получается. вот и все.


 
DiamondShark ©   (2007-12-24 20:18) [36]


> @!!ex ©   (24.12.07 20:16) [35]

См. Remarks к функции GetKeyboardState


 
Sapersky   (2007-12-24 20:20) [37]

Состояние обновлено частично в момент работы потока чтения.
Не видно обновления в потоке чтения, либо видно частично.


Так и фиг с ним. Это же проверка нажатия клавиш. На этом цикле не увидится - на следующем дойдёт. А нажать так, чтобы за один цикл всё пролетело, ни один юзер не сможет.

Пример из MSDN, если это тот, который с
int iValue;
BOOL fValueHasBeenComputed = FALSE;
- относится к порядку записи значений в память.
В данном случае порядок неважен.

GetKeyboardState
An application can call this function to retrieve the current status of all the virtual keys. The status changes as a thread removes keyboard messages from its message queue.


Обычно GetKeyboardState работает быстрее, чем отлавливание WM_KEYDOWN (т.е. реакция на нажатие кнопок лучше). Здесь же написано, что она фактически привязана к очереди сообщений. Странно...

Также странно и желание автора вопроса использовать GetKeyboardState в отдельном потоке. Неужели в основном не работает?
Как вариант, есть ещё GetAsyncKeyState/DirectInput.


 
oxffff ©   (2007-12-24 20:24) [38]


> DiamondShark ©   (24.12.07 20:11) [33]
>
> > oxffff ©   (24.12.07 19:52) [31]
>
> Это ты глупый. Не видишь разницы между общим правилом и
> частным случаем.

Частный случай, ты телепат?
Есть правила которых ты не знаешь.
Как раз ты говоришь о частном случае.

> > Это не атомарная операция.
>
> Конечно. Запись байта -- сильно не атомарная операция. ;
> )
> Я поторопился с оценкой "хорошая память". Ты опять забыл,
>  какой массив общий.

Массив общий только его состояние будет не согласовано.
Нажал кнопку, а результат позже чем ты ожидаешь.

> > Состояние обновлено частично в момент работы потока чтения.
>
>
> Да. Пол-байта записали. ;)

Ты реально бестолковый дятел.
Увы запись байта атомарна.
А вот состояние всего массива не согласовано.

> > Не видно обновления в потоке чтения, либо видно частично.
>
>
> Булеан значение частично -- это у блондинок.
>
> Ты за весь массив целиком боишься? Зря. Прикладные данные
> в нём такого характера, что это совершенно не критично.

Да ты что? Телепат что ли ты?
Прикинь нажал кнопку, а результата нет.

> > Опять пытаешься съехать.
> Опять твоё воображение.
> Ты почему-то решил, что я давал общий ответ, а не в контексте
> задачи, а потом коварно "съехал".
> Но твои церебральные тараканы -- твоя личная проблема.


Нет, Я это твоя проблема.


 
@!!ex ©   (2007-12-24 20:24) [39]

> Также странно и желание автора вопроса использовать GetKeyboardState
> в отдельном потоке. Неужели в основном не работает?
> Как вариант, есть ещё GetAsyncKeyState/DirectInput.

http://delphimaster.net/view/15-1198510244/

GetAsyncKeyState чем лучше?

DirectInput - не хочеться привязывать к директиксу. Да и не работал DI никогда.. а под дельфи так вообще с DX Не работал.


 
oxffff ©   (2007-12-24 20:26) [40]


> Sapersky   (24.12.07 20:20) [37]


А если прикинь нажал кнопку, а результата нет.
Так что увы это критично.


 
DiamondShark ©   (2007-12-24 20:28) [41]


> Нет, Я это твоя проблема.

Всё. Пипец. Ржу до слёз. :)

Лечись от манечки.


 
oxffff ©   (2007-12-24 20:31) [42]


> @!!ex ©   (24.12.07 20:24) [39]


C DI время отклика будет лучше. Гораздо.
Работать очень просто.

Код с моего движка.

DirectInput8.CreateDevice(GUID_SysMouse,DirectInputDeviceMouse,nil);
//if DirectInputDevice.SetCooperativeLevel(Handle,DISCL_BACKGROUND or DISCL_NONEXCLUSIVE)=DI_OK then ;//showmessage("DI_OK");

//DirectInputDeviceMouse.SetCooperativeLevel(Handle,DISCL_FOREGROUND);
DirectInputDeviceMouse.SetCooperativeLevel(Handle,DISCL_NONEXCLUSIVE or DISCL_BACKGROUND);
DirectInputDeviceMouse.SetDataFormat(c_dfDIMouse);
DirectInputDeviceMouse.Acquire;

DirectInput8.CreateDevice(GUID_SysKeyboard,DirectInputDeviceKeyboard,nil);
DirectInputDeviceKeyboard.SetCooperativeLevel(Handle,DISCL_FOREGROUND);
DirectInputDeviceKeyboard.SetDataFormat(c_dfDIKeyboard);
DirectInputDeviceKeyboard.Acquire;

Обработка

param.DirectInputDeviceKeyboard.GetDeviceState(sizeof(diKeys),@diKeys);
 if diKeys[DIK_ESCAPE]=$80 then param.DirectInputDeviceMouse.Unacquire;
 if diKeys[DIK_W]=$80 then Camera.Walk(300);
 if diKeys[DIK_S]=$80 then Camera.Walk(-300);
 if diKeys[DIK_A]=$80 then Camera.Yaw(-0.005);
 if diKeys[DIK_D]=$80 then Camera.Yaw(0.005);
if  param.DirectInputDeviceMouse.GetDeviceState(sizeof(DIMOUSESTATE),@MouseState)=DI _OK then
         begin
         if MouseState.rgbButtons[0]>0 then Camera.Walk(300);
         if MouseState.rgbButtons[1]>0 then Camera.Walk(-300);
         if MouseState.lX<>0 then  Camera.Yaw(-MouseState.lX/900);
         if MouseState.lY<>0 then  Camera.Pitch(-MouseState.lY/900);
         Camera.CalculateMatrixView(matrixView);
         setTransform(D3DTS_VIEW,matrixView);
         end;


 
DiamondShark ©   (2007-12-24 20:31) [43]


> oxffff ©   (24.12.07 20:26) [40]
>
> А если прикинь нажал кнопку, а результата нет.

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

Трагедия, однако. ;)

Опять фантазии. Теперь на тему критичности приложения.


 
oxffff ©   (2007-12-24 20:33) [44]


> DiamondShark ©   (24.12.07 20:28) [41]


А ты читай книжки и набивай всою пустую башку.
Родился в день знаний и не хрена не знаешь.
Еще и статьи пишешь.
Как тебя только допустили до статей?


 
@!!ex ©   (2007-12-24 20:33) [45]

> Ты реально бестолковый дятел.
> Увы запись байта атомарна.
> А вот состояние всего массива не согласовано.

ну и что?
Отклик за 20 мс(это примерно 40 фпс) никто не заметит. Ибо ниочем.
Так что то, что обновится только полокина массива - это фигня.
Меня волновало именно то, что не будет AV.


 
oxffff ©   (2007-12-24 20:36) [46]


> DiamondShark ©   (24.12.07 20:31) [43]


Ты реально даже прочитать не можешь SDK.

An application can call this function to retrieve the current status of all the virtual keys. The status changes as a thread removes keyboard messages from its message queue.


 
oxffff ©   (2007-12-24 20:38) [47]


> @!!ex ©   (24.12.07 20:33) [45]


Другой поток может вообще не увидить никакого обновления в течении длительного времени на мнопроцессорной машине.
Жмешь кнопку и никакого отклика.
Поток чтения не видит обновления.


 
DiamondShark ©   (2007-12-24 20:41) [48]


> oxffff ©   (24.12.07 20:36) [46]

Ты тормоз. ;)


 
@!!ex ©   (2007-12-24 20:46) [49]

Товарищи модераторы, пожалуйста закройте ветку!
Не хочеться, чтобы два хороших человека ругались из-за ерунды!
Задача решена через GetAsyncKeyState:

procedure TKeys.Update;
var
 Index:integer;
 Key:Smallint;
begin
 for Index:=0 to 255 do begin
   Key:=GetAsyncKeyState(Index);
   if Key And $8000<> OldKeys[Index] And $8000 then  begin
     Keys[Index]:=(Key And $8000)<>0;
     OldKeys[Index]:=Key;
   end;
 end;
end;


Sapersky, спасибо!


 
oxffff ©   (2007-12-24 20:47) [50]


> DiamondShark ©   (24.12.07 20:41) [48]
>
> > oxffff ©   (24.12.07 20:36) [46]
>
> Ты тормоз. ;)


Плакалъ.А ты замерь пересылку.
А прикинь нажал кнопку, и никакого результата.



Страницы: 1 2 вся ветка

Текущий архив: 2008.01.27;
Скачать: CL | DM;

Наверх




Память: 0.61 MB
Время: 0.019 c
3-1190377746
vajo
2007-09-21 16:29
2008.01.27
не открываются базы Interbase


2-1198823399
Максим В.
2007-12-28 09:29
2008.01.27
TPopupMenu +стандартное меню


2-1198665877
Flood_control
2007-12-26 13:44
2008.01.27
Сохранение в ini содержимого ListBox


1-1193213006
kyn66
2007-10-24 12:03
2008.01.27
Подобие EkRtf для Excel


15-1198348554
Dmitry S
2007-12-22 21:35
2008.01.27
Как настроить к себе людей?