2015-05-17 90 views
0

我想爲需要與來自其他程序和交換數據(接收/發送)的其他線程進行通信的複雜計算進行多線程迭代,我如何使它們進行通信?例如使用文件映射?這會工作嗎?多線程來減少CPU時間

+0

您需要它們交替,所以A進入第一上迭代1,則B,則A上迭代2,則B,等?還是有一些其他形式的同步需要? –

回答

1

假設要處理交替,那麼你將需要兩個信號量和每個過程將需要的代碼具有稍微不同序列的呼叫:

方法A:

SemA = CreateAndInitializeSemaphore(); 
SemB = CreateAndInitializeSemaphore(); 

for (i = 0; i < Numpoints; i++) 
{ 
    WaitForSemaphore(SemA); 
    …code for process A… 
    SignalSemaphore(SemB); 
} 

並且類似地對於B除了信號量被逆轉。

for (i = 0; i < Numpoints; i++) 
{ 
    WaitForSemaphore(SemB); 
    …code for process A… 
    SignalSemaphore(SemA); 
} 

請注意,當創建SemA時,需要設置它,以便A能夠立即訪問它。

所有信號函數名稱都需要映射到正確的實際系統調用。

+0

對於Windows的WaitForSingleObject()和ReleaseSemaphore()。如果你從兩個信號量開始計數爲1(每次執行1次ReleaseSemaphore()),那麼這兩個循環將保持同步。創建的進程的信號量需要是可繼承的。 – rcgldr

+0

@rcgldr:感謝有關函數名稱的信息。我認爲'semB'信號量需要爲零才能確保B等待A發出信號,而'semA'信號量需要爲1,以便A可以立即開始工作。 –

1

信號量和過程創建需要一些結構。

沒有警告定義是爲了防止使用sscanf或sprintf的警告。 abCmdLine具有進程B(pb.exe)的名稱和共享內存句柄的值。 (注 - 句柄是指針類型)。

循環中有1/2秒的睡眠,所以你可以看看它是如何工作的。在這個例子中,兩個循環同時運行。

更新 - 原始文章被編輯。以前它特別提到了進程A和進程B,以及名爲SemA,SemB的信號量和一個名爲count的計數器。隨着從原始帖子中刪除這些名字,閱讀此主題的人可能會想知道爲什麼這些名字在這裏的例子中被使用。本示例中的其他名稱遵循Microsoft/Windows匈牙利語表示樣式。

#define _CRT_SECURE_NO_WARNINGS 1 
#include <stdio.h> 
#include <windows.h> 

typedef struct SMEM_    /* shared memory offsets */ 
{ 
    HANDLE SemA; 
    HANDLE SemB; 
    int count; 
}SMEM, *PSMEM; 
static HANDLE hMem;    /* handle for shared memory */ 
static PSMEM psMem;    /* ptr to shared memory */ 

/* bInheritHandle = TRUE */ 
static SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), 
           NULL, TRUE}; 
static STARTUPINFO si = {sizeof(STARTUPINFO), 
         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 
/* hProcess = hThread = INVALID_HANDLE_VALUE */ 
static PROCESS_INFORMATION piB = {INVALID_HANDLE_VALUE, 
            INVALID_HANDLE_VALUE, 
            0, 0}; 

int main(int argc, char *argv[]) 
{ 
char abCmdLine[64]; 
    hMem = CreateFileMapping(INVALID_HANDLE_VALUE,&sa,PAGE_READWRITE,0, 
          sizeof(SMEM),NULL); 
    if(hMem == INVALID_HANDLE_VALUE){ 
     goto exit0;} 
    psMem = MapViewOfFile(hMem, FILE_MAP_WRITE, 0, 0, sizeof(SMEM)); 
    if(psMem == NULL){ 
     goto exit0;} 
    memset(psMem, 0, sizeof(SMEM)); 

    /* process A waits before psMem->count++ */ 
    psMem->SemA = CreateSemaphore(&sa,0,2,NULL); 
    if(psMem->SemA == INVALID_HANDLE_VALUE) 
     goto exit0; 
    /* process B waits for count to be updated */ 
    psMem->SemB = CreateSemaphore(&sa,0,2,NULL); 
    if(psMem->SemB == INVALID_HANDLE_VALUE) 
     goto exit0; 
    /* create process B */ 
    sprintf(abCmdLine, "pb.exe %p", hMem); 
    if(0 == CreateProcess(NULL, abCmdLine, NULL, NULL, TRUE, 
      CREATE_NEW_CONSOLE, NULL, NULL, &si, &piB)) 
     goto exit0; 
    for(psMem->count = 0; psMem->count < 20; psMem->count++){ 
     /* allow process B to use psMem->count */ 
     ReleaseSemaphore(psMem->SemB, 1, NULL); 
     printf("%d\n", psMem->count); 
     Sleep(500); 
     /* wait before psMem->count++ */ 
     WaitForSingleObject(psMem->SemA, INFINITE); 
    } 
    /* wait for process B to terminate */ 
    WaitForSingleObject(piB.hProcess, INFINITE); 
exit0: 
    if(piB.hThread != INVALID_HANDLE_VALUE) 
     CloseHandle(piB.hThread); 
    if(piB.hProcess != INVALID_HANDLE_VALUE) 
     CloseHandle(piB.hProcess); 
    if(psMem->SemB != INVALID_HANDLE_VALUE) 
     CloseHandle(psMem->SemB); 
    if(psMem->SemA != INVALID_HANDLE_VALUE) 
     CloseHandle(psMem->SemA); 
    if(hMem != INVALID_HANDLE_VALUE) 
     CloseHandle(hMem); 
    return(0); 
} 

處理B(pb.exe)

#define _CRT_SECURE_NO_WARNINGS 1 
#include <stdio.h> 
#include <windows.h> 

typedef struct SMEM_    /* shared memory offsets */ 
{ 
    HANDLE SemA; 
    HANDLE SemB; 
    int count; 
}SMEM, *PSMEM; 
static HANDLE hMem;    /* handle for shared memory */ 
static PSMEM psMem;    /* ptr to shared memory */ 

int main(int argc, char *argv[]) 
{ 
int done = 0;      /* done flag */ 
    sscanf(argv[1], "%p", &hMem); 
    psMem = MapViewOfFile(hMem, FILE_MAP_WRITE, 0, 0, sizeof(SMEM)); 
    if(psMem == NULL) 
     goto exit0; 
    while(!done){ 
     /* wait for psMem->count to be updated */ 
     WaitForSingleObject(psMem->SemB, INFINITE); 
     printf("%d\n", psMem->count); 
     Sleep(500); 
     done = psMem->count < 19 ? 0 : 1; 
     /* allow process A to update psMem->count */ 
     ReleaseSemaphore(psMem->SemA, 1, NULL); 
    } 
exit0: 
    return(0); 
} 
+0

已刪除電話的預先評論,因此我刪除了對這些評論的回覆,因爲上面的示例代碼涵蓋了之前評論中提出的問題。 – rcgldr