2016-05-28 3 views
-1

Я хочу для синхронизации потоков для печати от 1 до 20 с нечетными номерами, напечатанных thread1 и четных чисел, напечатанных thread2синхронизации потоков для двух потоков с использованием одного семафора

Я достиг этого с двумя семафоров.

Вопросы:

1) Может ли это быть достигнуто, используя только один семафор?

2) Есть ли эффективный способ достичь этого?

Если возможно, укажите пример.

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

Вместо использования семафоров, почему бы не использовать атомные типы? – Linus

+1

@ Linus вообще, потому что вы не можете дождаться их. –

ответ

0

Ну, можно использовать только один семафор, но каким-то хакерским способом. Вместо использования семафора, как мьютекс, вы можете использовать его для хранения фактического значения, а затем напечатать четные числа в потоке 2 и нечетные числа в потоке 1. Вот пример, но вместо печати от 1 до 20 он печатает от 20 до 1, но это может быть легко изменено, если требуется.

#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); 
} 

Однако семафоры редко используются таким образом, и поэтому я предлагаю использовать атомарные типы вместо, которые намного более современный и идеально подходит для вашего USECASE. Вот краткий пример:

#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); 
} 

Что касается производительности как единая программы семафора и программа на основе атомного типа работают намного быстрее, чем код, который вы указали. Однако в этом масштабе, когда вы используете только цифры в диапазоне от 1 до 20, различия в перфорации незначительны.

Смежные вопросы