2012-02-08 2 views
1

그래서 최근에 C++에서 제공된 SDK (소프트웨어 개발 키트)로 빌드 할 수있는 DLL로 확장 가능한 프로그램에서 속도 (CPU 사용 대)를 향상시키는 방법에 대해 생각하기 시작했습니다.원인 원본이 없지만 DLL을로드 할 수있는 프로그램의 경쟁 조건?

데이터 스레딩에 대한 연구를 시작한 후 전역 변수에 대한 연구를 시작했습니다. 필요한 경우 주 스레드가 변수를 호출하고 전체 기능을 실행하지 않습니다 (스레드가 처리합니다).

실제로 스레드가 응용 프로그램을 중단시킬 것으로 예상했기 때문에 실제로 결과에 놀랐습니다.

응용 프로그램의 개발자 포럼에 대한 토론을 시작했습니다. 다음과 같이 알려줍니다. "스레드 규칙 : 충돌이 발생하면 오류가 발생하고 오류가 발생하지 않으면 오류가 발생합니다." 그리고 : "사실, 그 코드는 충돌을 일으키지 않을 것이지만 변수가 손상 될 수 있습니다. 경주 위험이 발생하기 전에 문제없이 몇 달 동안 실행되는 멀티 스레드 프로그램에 대한 이야기를 들었습니다."

글쎄, '경기'가 실제로 경쟁 조건을 일으킬 수 있습니까?

주 응용 프로그램 (SA-MP, San Andreas Multiplayer)은 단일 스레드이며 이와 같이 컴파일됩니다.

내 테스트에 사용 된 코드 : [C++]

#ifdef OS_WINDOWS 
    void Thread::BackgroundCalculator(void *unused) 
#else 
    void *Thread::BackgroundCalculator(void *unused) 
#endif 
{ 
    float X; 
    float Y; 
    float Z; 
    while(true) 
    { 
     if(ENABLED == false) 
     { 
      continue; 
     } 
     for(int i = 0; i < MAX_PLAYERS; ++i) 
     { 
      if(IsPlayerConnected(i) == false) 
      { 
       speed[i] = -1.0f; 
       continue; 
      } 
      if(IsPlayerInAnyVehicle(i) == true) 
      { 
       GetVehicleVelocity(GetPlayerVehicleID(i),&X,&Y,&Z);//Is actually used by MAIN APPLICATION thread too... so should cause race condition? 
      } 
      else 
      { 
       GetPlayerVelocity(i,&X,&Y,&Z);//Is actually used by MAIN APPLICATION thread too... so should cause race condition? 
      } 
      speed[i] = sqrt(X*X+Y*Y+Z*Z);//called from my code.. thread 
     } 
     SLEEP(30); 
    } 

    EXIT_THREAD();//should be never reached.. 
} 

static cell AMX_NATIVE_CALL n_GetSpeed(AMX* amx, cell* params) 
{ 
    return amx_ftoc(speed[params[1]]);//returning to main thread, ftoc = FloatToCell 
} 

와 아주 여러 번 호출 할 때 가상 머신 (.amx 파일)에서 "n_GetSpeed". 그것은 충돌하지 않습니다. 또한 GetPlayerVelocity/GetVehicleVelocity를 주 스레드와 스레드에서 가능한 한 많이 호출 해 보았습니다. 여전히 충돌하지 않습니다. 전혀 기대하지 않는 것.

그렇다면 누군가가 경쟁 조건이 발생할 것이라고 말했을 때 어떻게 경쟁 조건을 일으키는 지 알고 싶습니다. 내가 만드는 중이라서 코드이 너무 내 페이지에서 오픈 소스 및 사용 가능한, 항상

__ (당연히 C에서/C++) : 당신이 전체 코드가 필요합니다 그냥 경우 http://gpb.googlecode.com/files/ThreadTest_R100.zip )

__

추가 참고 사항 : 나는 변수에만 액세스하고 변경하지 않는 것은 내가 변경하는 유일한 것은 속도 변수이며 두 번째 스레드에서만 수행됩니다.

+0

* 추가 ​​참고 사항 : 문제는 ... 변수에만 액세스하고 변경하지 않기 * - 그렇다면 경쟁 조건이 없습니다. 그렇습니까? 그들이 결코 변하지 않는다면 당신은 경쟁 조건을 가질 수 없습니다. 왜 유효한 메모리를 읽는다면 충돌이 발생합니까? –

+0

아, 응용 프로그램의 커뮤니티에서 충돌이 발생할 수 있다고 걱정했습니다. 관심있는 사람이 있다면 : http://forum.sa-mp.com/showthread.php?t=314452 나는 [ 나는 놀랐다. 하지만 이제는이 코드의 평화를 사용할 수 있습니다. :) –

+0

이것은 충돌 할 확률이 적지 만, 사실 * 후에 응용 프로그램에 스레드를 해킹하는 것은 몇 가지 문제를 야기 할 수 있습니다. 특히 나중에 다른 사람이 스레딩을 인식하지 못할 때 필자는 권장 할 포스트 코더를 만난 적이 없다. 스레드의 문제는 올바르게 수행 할 계획을 가지고 있으며, 대부분의 단일 스레드 게임에는 그렇게하지 않습니다. 대개 원래 코드는 절대 스파게티 shitpile입니다. 나는 SA가, 전체 TES 시리즈, NWN 시리즈 ... 피하는 것이 가장 좋습니다. – ssube

답변

2

수정중인 응용 프로그램에 대해 많이 알지 못합니다. 잠재적으로 충돌을 일으킬 수 있습니다.

당신은 당신이 읽는다고 말하면 모든 것이 잘되어야합니다. 그러나 주 스레드 (원래 프로그램)는 가장 확실하게 변수를 변경합니다. 일어날 수있는 한 가지는 IsPlayerInAnyVehicle을 호출하고 TRUE를 반환하면 FALSE로 변경되거나 차량이 변경되거나 플레이어가 종료되거나 플레이어가 종료되는 것입니다. 따라서 GetVehicleVelocity, GetPlayerVehicleID 또는 GetPlayerVelocity에 대한 호출이 잘못된 상황에서 불렸다. 이것이 충돌로 이어질 것입니까? 누가 알아. 그러나 적어도 코드는 100 % 건강하지 않습니다.

편집 : 호출하는 메서드가 구현되는 방식을 모른 채로이 코드가 스레드로부터 안전한지 여부를 알 수 없습니다. 약한 메모리 주문을 게임에 넣으면 모든 메모리 베리어는 적절한 메모리 장벽없이 꺼집니다.

+0

이 메소드는 메인 애플리케이션에서 가짜 AMX 객체를 만들어 구현됩니다. 그런 다음 가상 시스템에서만 액세스 할 수 있어야하는 응용 프로그램의 기본 기능을 사용합니다. 그러나 내가 가진 구현 DLL에서 호출 할 수 있습니다. GetPlayerVehicleID와 GetPlayerVelocity는 값을 '0'으로 설정하기 때문에 초당 0 단위를 얻습니다. @markgz - 동시에 다중 바이트 값을 읽거나 쓰는 방법은 없습니까? 또한 사용하고있는 구현은 다음과 같습니다. https://github.com/Zeex/sampgdk/ (마스터 브랜치) –

+0

@my 이전 주석, 함수는 플레이어가 연결되어 있지 않은 경우 0을 제공합니다. 그러나 플레이어가 움직이지 않으면 0이 될 수도 있습니다. –