Mutex блокировка потоков
Я новичок в многопоточном / процессном программировании. Итак, вот что мне нужно уточнить.
Обработать код
pthread_mutex_lock()
pthread_create(fooAPI(sharedResource)) //fooAPI creates another thread with shared resource that shares across processes.
pthread_mutex_unlock()
С помощью приведенного выше псевдокода процесс B может получить доступ sharedResource
если мьютекс не разблокирован?
Как я могу получить доступ к sharedResource из процесса B правильно?
Есть ли какая-нибудь четкая визуальная схема, которая объясняет отношения между мьютексами, потоками и процессами?
4 ответа
Что вам нужно сделать, это вызвать 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->sharedResource оставлено читателю в качестве упражнения.:-)
Кстати, я забыл заметить, что для мьютекса должен быть установлен атрибут PTHREAD_PROCESS_SHARED, чтобы pthreads работал во всех процессах.
Q1.) Если предположить, что процесс B пытается завладеть тем же мьютексом, который вы заблокировали в процессе A (вы исключили его из псевдокода), то нет, процесс B не может получить доступ к sharedResource, пока мьютекс заблокирован, поскольку он будет сидеть в ожидании блокировки мьютекса. пока он не будет освобожден процессом A. Он вернется из функции mutex_lock(), когда мьютекс заблокирован (или когда произойдет ошибка!)
Q2.) В процессе B убедитесь, что вы всегда блокируете мьютекс, обращаетесь к общему ресурсу, а затем разблокируете мьютекс. Кроме того, проверьте код возврата из процедуры mutex_lock( pMutex), чтобы убедиться, что вы действительно владеете мьютексом, и ТОЛЬКО разблокируйте мьютекс, если вы его заблокировали. Сделайте то же самое из процесса А.
Оба процесса должны в основном делать одно и то же при доступе к мьютексу.
lock () Если блокировка успешна, тогда {access sharedResource unlock ()}
Q3.) Да, есть много диаграмм: =) https://www.google.se/search?q=mutex+thread+process&rlz=1C1AFAB_enSE487SE487&um=1&ie=UTF-8&hl=en&tbm=isch&source=og&sa=N&tab=wi&ei=ErodUcSmKqf54QS6nYDoAw&biw=1200&bih=1730&sei=FbodUbPbB6mF4ATarIBQ
Ниже приведен фрагмент кода, который поможет вам понять концепцию 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;
}
Процесс состоит как минимум из одного потока (вспомним основную функцию). Многопоточный код будет просто порождать больше потоков. Мьютексы используются для создания замков вокруг общих ресурсов, чтобы избежать повреждения данных / неожиданного / нежелательного поведения. В основном это обеспечивает последовательное выполнение в асинхронной установке - требование, которое вытекает из неконстантных неатомарных операций над общими структурами данных.
Яркое описание того, какими будут мьютексы, когда люди (потоки) выстраиваются в очередь, чтобы посетить туалет (общий ресурс). В то время как один человек (поток) использует ванную для облегчения себя (неконстантная неатомарная операция), он / она должен убедиться, что дверь заперта (мьютекс), иначе это может привести к тому, что вас поймают полностью (нежелательное поведение))