c - 将程序与信号量同步



我和一位同事一起,负责使用信号量同步一个"手写"的C程序。 任务是在 int[4] 字段循环中移动1,其他条目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 Setupn");
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 个"编写器"进程。

问题是,完成后,数组中总是只有一个,但是在大约 10 次运行中,在 500 次运行中,我们得到了 printf()(代码中的***)的中间输出,就像 3 > 0 一样,在下一行0 < 2左右。

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

希望我能得到一些好提示

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

该程序同时

读取和写入共享的非原子变量。因此,它表现出竞争条件,并且其行为未根据 C 标准定义。假设您将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()移动到循环的末尾。

最新更新