使用一个信号量

时间:2016-05-28 12:43:35

标签: c multithreading synchronization mutex semaphore

我想同步线程从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);
}

1 个答案:

答案 0 :(得分: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);
}

然而,信号量很少以这种方式使用,因此我建议使用原子类型,而不是更现代,并且非常适合您的用例。这是一个简单的例子:

#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范围内的数字的情况下,性能差异可以忽略不计。