2016-05-28 20 views
-1

Ich mag Threads synchronisieren, von 1 bis 20 mit ungerader Zahl von thread1 und geraden Zahlen gedruckt von Thread2Thread-Synchronisation für zwei Threads unter Verwendung eines Semaphor

I dies mit zwei Semaphoren erreicht gedruckt zu drucken.

Fragen:

1) Kann dies nur ein Semaphor verwendet erreicht werden?

2) Gibt es einen effizienten Weg, dies zu erreichen?

Wenn möglich, bitte auch ein Beispiel angeben.

sem_t bin_sem1, bin_sem2; 
int count = 1; 

int main() 
{ 
    int ret; 
    pthread_t a_thread, b_thread; 

    ret = sem_init(&bin_sem1, 0, 1); 
    if (ret != 0) 
    { 
     perror("semaphore1 initialization failed\n"); 
     exit(EXIT_FAILURE); 
    } 
    ret = sem_init(&bin_sem2, 0, 0); 
    if (ret != 0) 
    { 
     perror("semaphore2 initialization failed\n"); 
     exit(EXIT_FAILURE); 
    } 

    ret = pthread_create(&a_thread, NULL, thread_fun1, NULL); 
    if (ret != 0) 
    { 
     perror("Thread1 creation failed"); 
     exit(EXIT_FAILURE); 
    } 

    ret = pthread_create(&b_thread, NULL, thread_fun2, NULL); 
    if (ret != 0) 
    { 
     perror("Thread2 creation failed"); 
     exit(EXIT_FAILURE); 
    } 

    printf("Waiting for threads to finish\n"); 
    ret = pthread_join(a_thread, NULL); 
    if (ret != 0) 
    { 
     perror("Thread1 join failed"); 
     exit(EXIT_FAILURE); 
    } 
    printf("Thread1 joined"); 

    ret = pthread_join(b_thread, NULL); 
    if (ret != 0) 
    { 
     perror("Thread2 join failed"); 
     exit(EXIT_FAILURE); 
    } 
    printf("Thread2 joined"); 

    exit(EXIT_SUCCESS); 
} 

void *thread_fun1(void *arg) 
{ 
    int val=0, val2=0; 
    while (count < 20) 
    { 
     sem_wait(&bin_sem1); 
     sem_getvalue(&bin_sem1, &val);sem_getvalue(&bin_sem2, &val2); 
     printf("T 1 : after wait : sem 1 = %d, sem 2 = %d\n", val, val2); 

     printf("T 1 : count = %d\n", count++); 

     sem_post(&bin_sem2); 
     sem_getvalue(&bin_sem1, &val);sem_getvalue(&bin_sem2, &val2); 
     printf("T 1 : after post : sem 1 = %d, sem 2 = %d\n", val, val2); 
    } 
    pthread_exit(NULL); 
} 
void *thread_fun2(void *arg) 
{ 
    int val=0, val2=0; 
    while (count < 20) 
    { 
     sem_wait(&bin_sem2); 
     sem_getvalue(&bin_sem1, &val);sem_getvalue(&bin_sem2, &val2); 
     printf("\t\t\t\t\t\tT 2 : after wait : sem 1 = %d, sem 2 = %d\n", val, val2); 

     printf("\t\t\t\t\t\tT 2 : count = %d\n", count++); 

     sem_post(&bin_sem1); 
     sem_getvalue(&bin_sem1, &val);sem_getvalue(&bin_sem2, &val2); 
     printf("\t\t\t\t\t\tT 2 : after post : sem 1 = %d, sem 2 = %d\n", val, val2); 
    } 
    pthread_exit(NULL); 
} 
+0

Anstatt Semaphore zu verwenden, warum nicht atomare Typen verwenden? – Linus

+1

@Linus im Allgemeinen, weil Sie nicht auf sie warten können. –

Antwort

0

Nun, das ist möglich, nur ein Semaphor zu verwenden, sondern in einer Art hacky Weise. Anstatt einen Semaphor wie einen Mutex zu verwenden, können Sie den tatsächlichen Wert verwenden und dann gerade Zahlen in Thread 2 und ungerade Zahlen in Thread 1 drucken. Hier ist ein Beispiel, aber anstelle von 1 bis 20 wird von 20 bis 20 gedruckt 1 aber das kann bei Bedarf leicht geändert werden.

#include <stdio.h> 
#include <stdlib.h> 
#include <pthread.h> 
#include <semaphore.h> 

void *a_func(void *arg) { 
    sem_t *mySem = (sem_t *) arg; 
    int value = 20; 

    while (value > 0) { 
    if (value % 2 == 1) { 
     printf("thread 1 : %d\n", value); 
     sem_wait(mySem); 
    } 
    sem_getvalue(mySem, &value); 
    } 
} 

void *b_func(void *arg) { 
    sem_t *mySem = (sem_t *) arg; 
    int value = 20; 

    while (value > 0) { 
    if (value % 2 == 0) { 
     printf("thread 2 : %d\n", value); 
     sem_wait(mySem); 
    } 
    sem_getvalue(mySem, &value); 
    } 
} 

int main() { 
    sem_t mySem; 
    pthread_t a_thread, b_thread; 

    if (sem_init(&mySem, 0, 20)) { 
    // handle error 
    } 

    if (pthread_create(&a_thread, NULL, a_func, &mySem)) { 
    // handle error 
    } 

    if (pthread_create(&b_thread, NULL, b_func, &mySem)) { 
    // handle error 
    } 

    // wait for threads to finish 
    pthread_join(a_thread, NULL); 
    pthread_join(b_thread, NULL); 
} 

Allerdings sind Semaphore selten auf diese Weise verwendet und deshalb schlage ich vor atomaren Typen stattdessen verwendet, die viel moderner sind und ist für Ihre usecase perfekt. Hier ist ein kurzes Beispiel:

#include <stdio.h> 
#include <stdlib.h> 
#include <pthread.h> 
#include <stdatomic.h> 

void *a_func(void *arg) { 
    atomic_int *myInt = (atomic_int *) arg; 
    int value = 20; 

    while (value > 0) { 
    if (value % 2 == 1) { 
     //printf("thread 1 : %d\n", value); 
     value = atomic_fetch_sub(myInt, 1) + 1; 
     continue; 
    } 
    value = atomic_load(myInt); 
    } 
} 

void *b_func(void *arg) { 
    atomic_int *myInt = (atomic_int *) arg; 
    int value = 20; 

    while (value > 0) { 
    if (value % 2 == 0) { 
     //printf("thread 2 : %d\n", value); 
     value = atomic_fetch_sub(myInt, 1) + 1; 
     continue; 
    } 
    value = atomic_load(myInt); 
    } 
} 

int main() { 
    atomic_int myInt = ATOMIC_VAR_INIT(20); // set myInt to 20 
    pthread_t a_thread, b_thread; 

    if (pthread_create(&a_thread, NULL, a_func, &myInt)) { 
    // handle error 
    } 

    if (pthread_create(&b_thread, NULL, b_func, &myInt)) { 
    // handle error 
    } 

    // wait for threads to finish 
    pthread_join(a_thread, NULL); 
    pthread_join(b_thread, NULL); 
} 

Was die Leistung sowohl der einzelnen Semaphore-Programm und das Atomtyp basierendes Programm läuft viel schneller als der Code, den Sie zur Verfügung gestellt. In diesem Maßstab, in dem Sie nur Zahlen im Bereich von 1 bis 20 verwenden, sind die Perforationsunterschiede vernachlässigbar.