[英]Multiple Processes and Threads synchronization and ordering in C
我要完成的工作是在每個新進程中創建3個進程和一個新線程,以處理匿名映射的共享內存。 我對多線程和IPC還是很陌生,所以也許我沒有正確使用它們,但是我嘗試了Mutexes,Semaphores和Condition Variables,而當我接近在它們之間傳遞內存時,它要么掛起,要么似乎沒有掛起。完全傳遞信息。
我想做的是:
我知道我可以使用管道和僅3個進程來完成此操作,但是我想嘗試使用共享內存和線程。
是否可以通過以下方式訂購流程:
會這樣運行嗎? 通常,對於N個進程和N個線程,有什么方法可以做到這一點? 我覺得我應該可以,但是我對此還不熟悉。 任何想法和建議表示贊賞,在此先感謝。
編輯:我在調用fork()時找到了解決方案,但是在進程中對被調用線程進行了重新排序。 請在下面查看示例。
更新的問題:我發現在某個線程中使用memcpy()時,我可以為一個緩沖區而不是另一個緩沖區更新共享內存中的緩沖區。 在下一個線程中,我的一個緩沖區應該是已滿,但另一個緩沖區卻沒有,即使快速檢查顯示在離開線程之前兩個緩沖區中都有數據? 我遇到了哪種並發錯誤? 想法和建議表示贊賞,在此先感謝。
這個問題相當籠統,廣泛而深刻。 因此,我的回答將使您初步了解多線程/多處理。 首先,我將這個問題分為兩個主要問題:1)單個進程內的線程同步。 2)單線程進程同步。 稍后,您可以組合(1)和(2),不要忘記混合線程和叉子造成的特殊問題和副作用。
假設我們有一個進程,該進程具有3個(通常為M)線程t1,t2和t3,這些線程應以強序列(t1,t2和t3)運行。 即使您完全按照此順序創建這些線程,也沒有人可以保證將按該順序啟動它們。 您可以通過迫使它們等待兩個條件變量c1和c2來阻止t2和t3的執行。 當t1和t2線程准備就緒時,上述條件變量將向t2和t3線程發出信號。 t1線程將“解鎖” c1變量,t2線程將“解鎖” c2。 因此,您所需要做的就是與兩個(或M-1)互斥鎖相關聯的兩個(或M-1)條件變量,以及兩個(或M-1)布爾值負責線程狀態。 這是一個簡化的代碼。 盡管它可以工作(您可以使用gcc -lpthread進行編譯),但是您的“真實”代碼應將變量組織成結構,檢查錯誤等。
#include <pthread.h>
#include <stdio.h>
// These are mentioned mutexes, conditional variables and booleans.
// They are global, so any thread can access them.
pthread_mutex_t m1 = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t c1 = PTHREAD_COND_INITIALIZER;
int t1_is_ready = 0;
pthread_mutex_t m2 = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t c2 = PTHREAD_COND_INITIALIZER;
int t2_is_ready = 0;
// This function is invoked by the t1 thread.
// It does not depend on conditional variables and always is executed first.
// When it's ready it sets its ready status to one and signal to the thread t2
// via c2, that the status has changed.
void* t1_work(void* arg)
{
pthread_mutex_lock(&m1);
printf("thread t1 does its work\n");
t1_is_ready = 1;
pthread_mutex_unlock(&m1);
pthread_cond_signal(&c1);
pthread_exit(NULL);
}
// This function is invoked by the t2 thread.
// It is blocked until t1 setis is ready status to 1.
// Pay your attention how to wait on a conditional variable:
// with locked mutex and in a loop, to prevent spurious wakes up.
void* t2_work(void* arg)
{
pthread_mutex_lock(&m1);
while(t1_is_ready == 0)
{
pthread_cond_wait(&c1, &m1);
}
pthread_mutex_unlock(&m1);
pthread_mutex_lock(&m2);
printf("thread t2 does its work\n");
t2_is_ready = 1;
pthread_mutex_unlock(&m2);
pthread_cond_signal(&c2);
pthread_exit(NULL);
}
// This function is invoked by the t3 thread.
void* t3_work(void* arg)
{
pthread_mutex_lock(&m2);
while(t2_is_ready == 0)
{
pthread_cond_wait(&c2, &m2);
}
printf("thread t3 does its work\n");
pthread_mutex_unlock(&m2);
pthread_exit(NULL);
}
int main(void)
{
pthread_t t1;
pthread_t t2;
pthread_t t3;
pthread_create(&t1, NULL, t1_work, NULL);
pthread_create(&t2, NULL, t2_work, NULL);
pthread_create(&t3, NULL, t3_work, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_join(t3, NULL);
return 0;
}
這是一篇不錯的文章,其中包含過程同步的代碼示例: http : //www.linuxdevcenter.com/pub/a/linux/2007/05/24/semaphores-in-linux.html?page=5由於您打算通過fork()函數創建您的進程,它們將被稱為“相關”。 如果您有3個(或N個)正在運行的進程,請創建2個(N-1)個信號燈,並以同步線程的方式使用它們。
感謝@MichaelGoren和一些細微的修改,我找到了解決方案。 我實質上是重新排序了按流程順序調用的線程。 我沒有使用信號量,而是讓我的父線程等待孩子完成。 所以,
如前所述,我還使用了一些共享內存。
為了它去了第二個孩子->第一個線程->第一個孩子->第二個線程->父母->第三個線程。
現在,我不確定這是否是萬無一失的,如果這可能不是並行的,請隨時糾正我。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.