多线程/流程编程的新手。 所以这就是我需要澄清的内容。
处理代码
pthread_mutex_lock()
pthread_create(fooAPI(sharedResource)) //fooAPI creates another thread with shared resource that shares across processes.
pthread_mutex_unlock()
使用上面的伪代码,如果未解锁互斥锁,进程B是否能够访问sharedResource
?
如何正确访问进程B中的sharedResource?
是否有任何清晰的可视化图解释互斥体,线程和进程之间的关系?
答案 0 :(得分:49)
您需要做的是调用pthread_mutex_lock来保护互斥锁,如下所示:
pthread_mutex_lock(&mutex);
执行此操作后,在此线程中调用pthread_mutex_lock(mutex)
之前,对pthread_mutex_unlock
的任何其他调用都不会返回。因此,如果您尝试调用pthread_create,您将能够创建一个新线程,并且该线程将能够(错误地)使用共享资源。您应该从pthread_mutex_lock
函数中调用fooAPI
,这将导致函数等待共享资源可用。
所以你会有这样的事情:
#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-&gt; sharedResource进行更改留给读者练习。 : - )
顺便说一下,忘记了互斥锁必须设置PTHREAD_PROCESS_SHARED属性,以便pthreads可以跨进程工作。
答案 1 :(得分:3)
Q1。)假设进程B尝试获取您在进程A中锁定的相同互斥锁的所有权(您将其从伪代码中删除)然后否,进程B无法在互斥锁被锁定时访问sharedResource,因为它将等待锁定互斥锁,直到它被进程A释放。当互斥锁被锁定时(或发生错误时,它将从mutex_lock()函数返回!)
Q2。)在进程B中,确保始终锁定互斥锁,访问共享资源,然后解锁互斥锁。另外,检查来自mutex_lock(pMutex)例程的返回码,以确保您实际拥有互斥锁,并且只有锁定了互斥锁才能解锁互斥锁。从流程A做同样的事。
访问互斥锁时,两个进程基本上应该做同样的事情 锁() 如果锁定成功,那么{ 访问sharedResource 开锁() }
答案 2 :(得分:2)
一个进程由至少一个线程组成(想想主要功能)。多线程代码只会产生更多线程。 互斥锁用于在共享资源周围创建锁,以避免数据损坏/意外/不需要的行为。基本上它提供了在异步设置中的顺序执行 - 其要求源于对共享数据结构的非const非原子操作。
生动地描述了人们(线程)排队访问洗手间(共享资源)的情况。当一个人(线程)正在使用浴室放松他/她自己(非常规非原子操作)时,他/她应该确保门被锁定(互斥锁),否则它可能导致被完全蒙太奇(不需要的行为) )
答案 3 :(得分:2)
下面,代码片段将帮助您理解互斥锁定解锁概念。尝试干运行代码。 (通过改变等待时间和处理时间,你可以建立你的理解)。
代码供您参考:
#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;
}