【问题标题】:Thread synchronisation using semaphore for c使用信号量进行线程同步
【发布时间】:2017-03-22 10:38:13
【问题描述】:

我正在编写一个 c 程序来创建三个线程(1,2,3),这样在任何给定的时间点,只有一个线程必须执行并在控制台上按 123123123123 的顺序打印输出............ .

我正在使用信号量进行同步。

我编写的代码有问题。该代码不会按 123123 的顺序打印它...该顺序是随机的,并且会在一段时间后停止。

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

sem_t sem_1;

void *func1(void *arg){

    int err1=0;

    while(1){
            err1=sem_wait(&sem_1);
            assert(err1==0);
            printf("thread 1\n");
    }
    //return NULL;
}

void *func2(void *arg){

   int err2=0;

    while(1){
            err2=sem_wait(&sem_1);
            assert(err2==0);
            printf("thread 2\n");
    }
   // return NULL;
}

void *func3(void *arg){

  int err3=0;

   while(1){
            err3=sem_wait(&sem_1);
            assert(err3==0);
            printf("thread 3\n");
    }
   // return NULL;
}

int main(){

    pthread_t *t1,*t2,*t3;
    int i=0,rc=0,c1=0,c2=0,c3=0;
    t1=(pthread_t *)malloc(sizeof(*t1));
    t2=(pthread_t *)malloc(sizeof(*t2));
    t3=(pthread_t *)malloc(sizeof(*t3));

    i=sem_init(&sem_1,0,1);
    assert(i==0);

    c1=pthread_create(t1,NULL,func1,NULL);
    assert(c1==0);

    c2=pthread_create(t2,NULL,func2,NULL);
    assert(c2==0);

    c3=pthread_create(t3,NULL,func3,NULL);
    assert(c3==0);

    while(1){
            rc=sem_post(&sem_1);
            assert(rc==0);
            sleep(1);
    }
    return 0;
}

【问题讨论】:

  • 创建一个初始值为2的计数信号量,你会得到想要的结果。但顺序相反。

标签: c multithreading synchronization


【解决方案1】:

你为什么会期望它们按顺序排列?

  • 您的线程在不同的等待之间执行操作,并且根据系统调度程序,这些可能需要不同的时间。
  • printf 是一种缓冲操作,可让您独占访问共享资源。所以除了你的信号量之外,还有一个隐藏的锁,它也调节你的线程的进度。不要指望打印是按顺序显示的,即使调用本身是按顺序显示的。

那么,最后,在这里使用assert 确实是一个非常糟糕的主意。所有sem_t 操作都可能(并且将会)虚假地失败,所以仅仅因为这样的失败而中止真的很糟糕。

事实上,sem_t 确实是一个低级工具,如果没有检查返回值,并且如果这样的调用失败,你不应该在没有备用策略的情况下使用它。

【讨论】:

  • 谢谢詹斯。我将对代码进行相关更改,如有任何进一步的疑问,我会回复您。
【解决方案2】:

当然。我看不到任何与订单相关的同步机制。

实现严格顺序的一种选择是每个线程有一个信号量:

sem_t sem[3];

// ...

while(1) {
        for(n = 0; n < 3; n++) {
                rc=sem_post(&sem[n]);
                assert(rc==0);
        }

        sleep(1);
}

【讨论】:

  • 检查@JensGustedt 的答案!
  • 哦,好吧。会尝试相同的。谢谢。
【解决方案3】:

下面的代码将有助于解决问题,每个线程使用一个信号量来实现同步。信号量的初始值完成了这项工作。使用 usleep 按顺序启动线程以获得所需的输出。同样可以通过使用 Mutex lock 和 cond 变量来完成

//declaring semaphore 
sem_t sema1;
sem_t sema2;
sem_t sema3;

void* t1(void *arg)
{
for(int j=0;j<10;j++)
{
    sem_wait(&sema1);
    printf("Thread 1 \n");
    sem_post(&sema2);
}       
printf("T1 return\n");
return NULL;
}
void* t2(void *arg)
{
for(int j=0;j<10;j++)
{
    sem_wait(&sema2);
    printf("Thread 2 \n");
    sem_post(&sema3);
}
printf("T2 return\n");
return NULL;
}

void* t3(void *arg)
{
for(int j=0;j<10;j++)
{
    sem_wait(&sema3);
    printf("Thread 3 \n");
    sem_post(&sema1);
}    
printf("T3 return \n");
return NULL;
}

int main()
{
pthread_t tid1, tid2,tid3;
sem_init(&sema1,0,1);
sem_init(&sema2,0,0);
sem_init(&sema3,0,0);
pthread_create(&tid1, NULL, t1, NULL);
usleep(100);
pthread_create(&tid2, NULL, t2, NULL);
usleep(100);
pthread_create(&tid3, NULL, t3, NULL);

pthread_join(tid3, NULL);
pthread_join(tid2, NULL);
pthread_join(tid1, NULL);
sem_destroy(&sema1);
sem_destroy(&sema2);
sem_destroy(&sema3);
return 0;
}

【讨论】:

    猜你喜欢
    • 2015-04-13
    • 1970-01-01
    • 2012-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-31
    • 1970-01-01
    相关资源
    最近更新 更多