簡體   English   中英

C中的多個進程和線程同步和排序

[英]Multiple Processes and Threads synchronization and ordering in C

我要完成的工作是在每個新進程中創建3個進程和一個新線程,以處理匿名映射的共享內存。 我對多線程和IPC還是很陌生,所以也許我沒有正確使用它們,但是我嘗試了Mutexes,Semaphores和Condition Variables,而當我接近在它們之間傳遞內存時,它要么掛起,要么似乎沒有掛起。完全傳遞信息。

我想做的是:

  1. 第一個fork()進程創建一個線程並從文件中讀取。
  2. 使新線程處理共享內存以對其進行更改的第二個過程。
  3. 創建線程以再次更改共享內存,然后將其輸出到文件的第三個過程。

我知道我可以使用管道和僅3個進程來完成此操作,但是我想嘗試使用共享內存和線程。

是否可以通過以下方式訂購流程:

  • 第一進程->第一線程->第二進程->第二線程->第三進程->第三線程

會這樣運行嗎? 通常,對於N個進程和N個線程,有什么方法可以做到這一點? 我覺得我應該可以,但是我對此還不熟悉。 任何想法和建議表示贊賞,在此先感謝。

編輯:我在調用fork()時找到了解決方案,但是在進程中對被調用線程進行了重新排序。 請在下面查看示例。

更新的問題:我發現在某個線程中使用memcpy()時,我可以為一個緩沖區而不是另一個緩沖區更新共享內存中的緩沖區。 在下一個線程中,我的一個緩沖區應該是已滿,但另一個緩沖區卻沒有,即使快速檢查顯示在離開線程之前兩個緩沖區中都有數據? 我遇到了哪種並發錯誤? 想法和建議表示贊賞,在此先感謝。

這個問題相當籠統,廣泛而深刻。 因此,我的回答將使您初步了解多線程/多處理。 首先,我將這個問題分為兩個主要問題:1)單個進程內的線程同步。 2)單線程進程同步。 稍后,您可以組合(1)和(2),不要忘記混合線程和叉子造成的特殊問題和副作用。

1.線程同步。

假設我們有一個進程,該進程具有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;
}

2.流程同步

這是一篇不錯的文章,其中包含過程同步的代碼示例: http : //www.linuxdevcenter.com/pub/a/linux/2007/05/24/semaphores-in-linux.html?page=5由於您打算通過fork()函數創建您的進程,它們將被稱為“相關”。 如果您有3個(或N個)正在運行的進程,請創建2個(N-1)個信號燈,並以同步線程的方式使用它們。

感謝@MichaelGoren和一些細微的修改,我找到了解決方案。 我實質上是重新排序了按流程順序調用的線程。 我沒有使用信號量,而是讓我的父線程等待孩子完成。 所以,

  1. 我在第一個過程中調用了fork(),並告訴父級等待其子級。 在此和下一個fork()之間也有一個Pipe。 我在這個父母中叫我的第三個線程。
  2. 我調用了下一個進程,使其等待其子進程,並在其中放入第二個線程。 現在,這個即將成為其自身父調用方的孩子在該孩子和最后一個孩子之間有了另一個管道。
  3. 我在最后一個孩子中打了我的第一個線程。

如前所述,我還使用了一些共享內存。

為了它去了第二個孩子->第一個線程->第一個孩子->第二個線程->父母->第三個線程。

現在,我不確定這是否是萬無一失的,如果這可能不是並行的,請隨時糾正我。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM