使用信号量同步程序

时间:2015-06-15 18:03:32

标签: c synchronization semaphore

与同事一起,我的任务是使用信号量同步“手写”C程序。任务是将1移动到int [4]字段循环中,其他条目为0

#include "workers.h"
#include "semaphores.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>





//-----------------------------------------------------------------------------
// global variables (all volatile!)
//-----------------------------------------------------------------------------

#define SIZE 4

volatile int ring[4];
volatile int von_position;
volatile int nach_position;
volatile semaphore semaphoren[4];
//-----------------------------------------------------------------------------
// call text_setup() once before starting the test
//-----------------------------------------------------------------------------

void test_setup(void) {
  printf("Test Setup\n");
for(int i= 0; i<4; i++){
  semaphoren[i] = sem_init(1);
}
von_position = 0;
nach_position = 1;
  readers=0; // maximal 1 (nicht veraendern!)
  writers=4; // maximal 19 
}

//-----------------------------------------------------------------------------
// test_end() is called after all workers have finished
//-----------------------------------------------------------------------------

void test_end(void) {
    for(int i = 0; i<4; i++){
        printf("%i ", ring[i]);
}

}

//-----------------------------------------------------------------------------
// those 4 workers execute in parallel
//-----------------------------------------------------------------------------

void writer(long my_id) {
for(int i =0; i<500; i++){
    sem_p(semaphoren[my_id]);
    printf("Writer %i :, %i>%i \n",(int) my_id, von_position, nach_position); // ***
    ring[von_position] = 0;
    ring[nach_position] = 1;
    sem_v(semaphoren[my_id]);
    if(von_position == 3){von_position = 0;}
    else von_position ++;
    if(nach_position == 3) {nach_position = 0;}
    else nach_position ++;

}

}

void reader(long my_id) {
}

这是从给我们的旧环形缓冲区程序派生的。它使用4个“作家”进程。

问题是,完成后,阵列中总会有一个,但是在ca.在500次运行中的10次中,我们得到了printf()(代码中的***)的中间输出,如3 > 0,在下一行0 < 2左右。

到目前为止,尝试了很多,但没有成功。

希望我能得到一些好的提示

2 个答案:

答案 0 :(得分:0)

示例代码不会“移动”1,而只是存储0和1。我的猜测是线程被认为是以同步方式移动元素。线程0从环[0]移动到环[1],线程1从环[1]移动到环[2],...线程3从环[3]移动到环[0]。线程可以全部读取并且全部并行写入,但需要同步以防止读取和写入之间的冲突。使用4个信号量似乎是一种实现它的简单方法。

答案 1 :(得分:0)

该程序同时读取和写入共享的非原子变量。因此它显示竞争条件,并且根据C标准,其行为是 undefined 。假设您将volatile更改为_Atomic,并使用atomic_load_explicit(x, memory_order_seq_cst)/atomic_store_explicit(x, memory_order_seq_cst)将所有加载/存储交换为原子变量,那么

void writer(long my_id)
{
  for(int i =0; i<500; i++)
  {
    sem_p(semaphoren[my_id]);
    printf("Writer %i :, %i>%i \n",(int) my_id, von_position, nach_position); 
    ring[von_position] = 0;
    ring[nach_position] = 1;
    sem_v(semaphoren[my_id]);
    if(von_position == 3){von_position = 0;}
    else von_position ++;
    if(nach_position == 3) {nach_position = 0;}
    else nach_position ++;
  }
}

仍然仍然sem_v()和第一个if()之间,if()else之间中断,等等。特别是,第一个writer()可以在递增von_position(模4)之后中断,递增nach_position之前中断。因此,下一位作者会看到von_position == nach_position,如果 作者在同一个地方被打断,下一位作家将会看到von_position > nach_position,等等。实际上,您应该将sem_v()移动到循环的末尾。