マルチスレッド/プロセスプログラミングが初めてです。だからここに私が明確にする必要があるものです。
プロセスAコード
pthread_mutex_lock()
pthread_create(fooAPI(sharedResource)) //fooAPI creates another thread with shared resource that shares across processes.
pthread_mutex_unlock()
上記の擬似コードで、mutexがロック解除されていない場合、プロセスBはsharedResource
にアクセスできますか?
プロセスBからsharedResourceに正しくアクセスするにはどうすればよいですか?
ミューテックス、スレッド、プロセス間の関係を説明する明確な視覚的な図はありますか?
次のように、pthread_mutex_lockを呼び出してミューテックスを保護する必要があります。
_pthread_mutex_lock(&mutex);
_
これを行うと、このスレッドで_pthread_mutex_unlock
_を呼び出すまで、pthread_mutex_lock(mutex)
への他の呼び出しは戻りません。したがって、pthread_createを呼び出そうとすると、新しいスレッドを作成でき、そのスレッドは(誤って)共有リソースを使用できます。 fooAPI
関数内から_pthread_mutex_lock
_を呼び出す必要があります。これにより、関数は共有リソースが利用可能になるまで待機します。
したがって、次のようなものがあります。
_#include <pthread.h>
#include <stdio.h>
int sharedResource = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* fooAPI(void* param)
{
pthread_mutex_lock(&mutex);
printf("Changing the shared resource now.\n");
sharedResource = 42;
pthread_mutex_unlock(&mutex);
return 0;
}
int main()
{
pthread_t thread;
// Really not locking for any reason other than to make the point.
pthread_mutex_lock(&mutex);
pthread_create(&thread, NULL, fooAPI, NULL);
sleep(1);
pthread_mutex_unlock(&mutex);
// Now we need to lock to use the shared resource.
pthread_mutex_lock(&mutex);
printf("%d\n", sharedResource);
pthread_mutex_unlock(&mutex);
}
_
編集:プロセス間でリソースを使用する場合も、これと同じ基本的なアプローチに従いますが、メモリを他のプロセスにマップする必要があります。 shmemを使用した例を次に示します。
_#include <stdio.h>
#include <unistd.h>
#include <sys/file.h>
#include <sys/mman.h>
#include <sys/wait.h>
struct shared {
pthread_mutex_t mutex;
int sharedResource;
};
int main()
{
int fd = shm_open("/foo", O_CREAT | O_TRUNC | O_RDWR, 0600);
ftruncate(fd, sizeof(struct shared));
struct shared *p = (struct shared*)mmap(0, sizeof(struct shared),
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
p->sharedResource = 0;
// Make sure it can be shared across processes
pthread_mutexattr_t shared;
pthread_mutexattr_init(&shared);
pthread_mutexattr_setpshared(&shared, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&(p->mutex), &shared);
int i;
for (i = 0; i < 100; i++) {
pthread_mutex_lock(&(p->mutex));
printf("%d\n", p->sharedResource);
pthread_mutex_unlock(&(p->mutex));
sleep(1);
}
munmap(p, sizeof(struct shared*));
shm_unlink("/foo");
}
_
P-> sharedResourceを変更するプログラムを作成することは、読者の課題として残されています。 :-)
ところで、mutexにはPTHREAD_PROCESS_SHARED属性が設定されている必要があり、pthreadsがプロセス間で機能することに注意するのを忘れていました。
Q1。)プロセスBがプロセスAでロックした同じmutexの所有権を取得しようとすると(疑似コードから除外した)、いいえプロセスAによって解放されるまで。mutexがロックされると(またはエラーが発生すると)mutex_lock()関数から戻ります。
Q2。)プロセスBでは、必ずミューテックスをロックし、共有リソースにアクセスしてから、ミューテックスをアンロックしてください。また、mutex_lock(pMutex)ルーチンからのリターンコードをチェックして、実際にmutexを所有していることを確認し、ロックしている場合はmutexのみをロック解除します。プロセスAから同じことを行います。
両方のプロセスは、mutexにアクセスするときに基本的に同じことを行う必要があります。
lock()ロックが成功した場合、{access sharedResource unlock()}
以下のコードスニペットは、mutex-lock-unlockの概念を理解するのに役立ちます。コードをドライランします。 (さらに、待機時間と処理時間を変えることにより、理解を深めることができます)。
参照用のコード:
#include <stdio.h>
#include <pthread.h>
void in_progress_feedback(int);
int global = 0;
pthread_mutex_t mutex;
void *compute(void *arg) {
pthread_t ptid = pthread_self();
printf("ptid : %08x \n", (int)ptid);
int i;
int lock_ret = 1;
do{
lock_ret = pthread_mutex_trylock(&mutex);
if(lock_ret){
printf("lock failed(%08x :: %d)..attempt again after 2secs..\n", (int)ptid, lock_ret);
sleep(2); //wait time here..
}else{ //ret =0 is successful lock
printf("lock success(%08x :: %d)..\n", (int)ptid, lock_ret);
break;
}
} while(lock_ret);
for (i = 0; i < 10*10 ; i++)
global++;
//do some stuff here
in_progress_feedback(10); //processing-time here..
lock_ret = pthread_mutex_unlock(&mutex);
printf("unlocked(%08x :: %d)..!\n", (int)ptid, lock_ret);
return NULL;
}
void in_progress_feedback(int prog_delay){
int i=0;
for(;i<prog_delay;i++){
printf(". ");
sleep(1);
fflush(stdout);
}
printf("\n");
fflush(stdout);
}
int main(void)
{
pthread_t tid0,tid1;
pthread_mutex_init(&mutex, NULL);
pthread_create(&tid0, NULL, compute, NULL);
pthread_create(&tid1, NULL, compute, NULL);
pthread_join(tid0, NULL);
pthread_join(tid1, NULL);
printf("global = %d\n", global);
pthread_mutex_destroy(&mutex);
return 0;
}
プロセスは、少なくとも1つのスレッドで構成されます(メイン関数を考えてください)。マルチスレッドコードは、より多くのスレッドを生成します。ミューテックスを使用して、共有リソースの周りにロックを作成し、データの破損/予期しない/望ましくない動作を回避します。基本的に、非同期セットアップでの順次実行を提供します。これは、共有データ構造での非const非原子操作に由来する要件です。
人(スレッド)がトイレ(共有リソース)を訪問するために待ち行列に入れている場合、ミューテックスがどのようなものであるかの鮮明な説明。 1人(スレッド)がバスルームを使用して自分を楽にしている間(非const非原子操作)、ドアがロックされていること(mutex)を確認する必要があります。 )