Замки блокировки Mutex - программирование
Подтвердить что ты не робот

Замки блокировки 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 правильно?

Есть ли какая-либо четкая визуальная диаграмма, которая объясняет взаимосвязь между мьютексами, потоками и процессами?

4b9b3361

Ответ 1

Что вам нужно сделать, так это вызвать 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 будут работать через процессы.

Ответ 2

Q1.) Предполагая, что процесс B пытается завладеть тем же мьютексом, который вы заблокировали в процессе A (вы оставили это из своего псевдокода), тогда нет, процесс B не может получить доступ к sharedResource, пока мьютекс заблокирован, так как он будет сидеть в ожидании блокируйте мьютекс до тех пор, пока он не будет освобожден процессом A. Он вернется из функции mutex_lock(), когда мьютекс заблокирован (или когда возникает ошибка!)

Q2.) В процессе B убедитесь, что вы всегда блокируете мьютекс, получаете доступ к общему ресурсу и затем разблокируете мьютексы. Кроме того, проверьте код возврата из процедуры mutex_lock (pMutex), чтобы убедиться, что вы действительно владеете мьютексом, и ТОЛЬКО разблокируйте мьютекс, если вы заблокировали его. Сделайте то же самое из процесса А.

Оба процесса должны в основном делать то же самое при доступе к мьютексу.
замок() Если блокировка выполнена успешно, тогда { доступ к sharedResource разблокировать() }

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

Ответ 3

Ниже, фрагмент кода, поможет вам понять концепцию 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;
}

Ответ 4

Процесс состоит из по крайней мере одного потока (думайте о главной функции). Многопоточный код просто порождает больше потоков. Мьютексы используются для создания блокировок вокруг общих ресурсов, чтобы избежать повреждения данных/непредвиденного/нежелательного поведения. В основном это обеспечивает последовательное выполнение в асинхронной установке - требование, для которого проистекает из неконстантных неатомных операций в общих структурах данных.

Яркое описание того, какие мьютексы будут иметь место, когда люди (потоки) ожидают посещения туалета (общий ресурс). В то время как один человек (нить) использует ванну, ослабляющую себя (неконстантную неатомную операцию), он должен обеспечить блокировку двери (мьютекс), иначе это может привести к полному захвату (нежелательное поведение )