ดูเหมือนว่าสัญญาณไม่ทำงานอย่างถูกต้องกับหลายเธรด

ฉันพยายามเขียนตัวอย่างเธรดหลายรายการด้วย C ซึ่งก็คือตัวเลขที่ได้รับจากผู้ใช้และตัวเลขรวมในสองเธรด

ด้ายอยู่ห่างจากกันโดยตรง จากหน้าไปหลังและหลังไปหน้า

ฉันใช้เซมาฟอร์เพื่อจัดการตัวแปรส่วนกลาง แต่เอาต์พุตแสดงว่าเซมาฟอร์ทำงานไม่ถูกต้อง

เกิดอะไรขึ้น?

ผลลัพธ์ของรหัส:

Array size? :10
Array of contents? :4 2 8 1 5 3 7 9 6 10
Thread_1 > read 4, sum is = 4 
Thread_1 > read 2, sum is = 6 
Thread_1 > read 8, sum is = 14 
Thread_1 > read 1, sum is = 15 
Thread_1 > read 5, sum is = 20 
Thread_1 > read 3, sum is = 23 
Thread_1 > read 7, sum is = 30 
Thread_1 > read 9, sum is = 39 
Thread_1 > read 6, sum is = 45 
Thread_1 > read 10, sum is = 55 
Thread_1 > End. 
Thread_2 > End. 

รหัส :

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

int *array; //Global integer array
int sum;    //Global sum variable
int counter = 0;

sem_t mutex;

void *front_to_back( void *val )
{
  int SIZE;
  SIZE = *((int *) val);

  while (1)
  {
    sem_wait(&mutex);

    if( counter != SIZE )
    {
      sum = sum + array[counter];

      printf("Thread_1 > read %d, sum is = %d \n", array[counter], sum);

      counter++;

    }else
    {
      printf("Thread_1 > End. \n");

      sem_post(&mutex);

      break;
    }

    sem_post(&mutex);
  }
}


void *back_to_front( void *val )
{
  int SIZE;
  SIZE = *((int *) val);

  int i=1;

  while (1)
  {
    sem_wait(&mutex);

    if( counter != SIZE )
    {
      sum = sum + array[SIZE - i];

      printf("Thread_2 > read %d, sum is = %d \n", array[SIZE - i], sum);

      counter++;
      i++;

    }else
    {
      printf("Thread_2 > End. \n");

      sem_post(&mutex);

      break;
    }

    sem_post(&mutex);
  }
}

main(){

  int SIZE;

  printf("Array size? :");
  scanf("%d", &SIZE);

  array = malloc(SIZE*sizeof(int));

  int i=0;

  printf("Array of contents? :");
  for (i ; i<SIZE ; i++)
  {
    scanf("%d", &array[i]);
  }

  pthread_t t[2];

  sem_init(&mutex, 0, 1);

  pthread_create(&t[1], NULL, front_to_back, (void *) &SIZE );
  pthread_create(&t[2], NULL, back_to_front, (void *) &SIZE );

  pthread_join(t[1],NULL);
  pthread_join(t[2],NULL);

  free(array);
  sem_destroy(&mutex);

}

person Erol Guzoğlu    schedule 17.05.2015    source แหล่งที่มา


คำตอบ (1)


คุณควรใช้ t[0] และ t[1] ใน main(): อาร์เรย์ขนาด N มีดัชนีที่ถูกต้องใน 0..N-1 ดังนั้นก่อนอื่น ให้แก้ไขสิ่งนั้น นี่คือรหัสที่ถูกต้อง:

pthread_create(&t[0], NULL, front_to_back, (void *) &SIZE );
pthread_create(&t[1], NULL, back_to_front, (void *) &SIZE );

pthread_join(t[0],NULL);
pthread_join(t[1],NULL);

ตามหลักการแล้ว คุณควรตรวจสอบว่า malloc() และ pthread_create() สำเร็จหรือไม่ ฟังก์ชันเหล่านี้สามารถกลับมาพร้อมกับข้อผิดพลาด และคุณควรจัดการมัน รหัสของคุณเพิกเฉยต่อข้อผิดพลาด (ด้วยการเข้าถึงแบบนอกขอบเขต คุณโชคดีจริงๆ ที่มันใช้งานได้)

นอกจากนี้ เหตุใดคุณจึงใช้เซมาฟอร์เหมือนกับว่าเป็น mutex เซมาฟอร์ไม่จำเป็นจริงๆ ในที่นี้ เมื่อคุณไม่ต้องการพลังและความยืดหยุ่นของเซมาฟอร์ เพียงแค่ใช้ mutex ข้อแตกต่างที่สำคัญประการหนึ่งคือเซมาฟอร์อนุญาตให้คุณรอบนเธรดหนึ่งและโพสต์บนอีกเธรดหนึ่ง ในขณะที่เธรดที่ได้รับเธรดนั้นจะต้องปลดล็อก mutex

ดังนั้น การใช้เซมาฟอร์ที่มี mutex เพียงพออาจช่วยปกปิดข้อผิดพลาดในโค้ดของคุณได้ ดังนั้นฉันจะใช้ mutex แทน นี่คือโค้ดที่มีการเปลี่ยนแปลงทั้งหมด:

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>

int *array; //Global integer array
int sum;    //Global sum variable
int counter = 0;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *front_to_back( void *val )
{
    int SIZE;
    SIZE = *((int *) val);

    while (1)
    {
        pthread_mutex_lock(&mutex);

        if( counter != SIZE )
        {
            sum = sum + array[counter];

            printf("Thread_1 > read %d, sum is = %d \n", array[counter], sum);

            counter++;

        }else
        {
            printf("Thread_1 > End. \n");

            pthread_mutex_unlock(&mutex);

            break;
        }

        pthread_mutex_unlock(&mutex);
    }
    return NULL;
}


void *back_to_front( void *val )
{
    int SIZE;
    SIZE = *((int *) val);

    int i=1;

    while (1)
    {
        pthread_mutex_lock(&mutex);

        if( counter != SIZE )
        {
            sum = sum + array[SIZE - i];

            printf("Thread_2 > read %d, sum is = %d \n", array[SIZE - i], sum);

            counter++;
            i++;

        }else
        {
            printf("Thread_2 > End. \n");

            pthread_mutex_unlock(&mutex);

            break;
        }

        pthread_mutex_unlock(&mutex);
    }
    return NULL;
}

int main(void) {

    int SIZE;

    printf("Array size? :");
    scanf("%d", &SIZE);

    array = malloc(SIZE*sizeof(int));

    int i=0;

    printf("Array of contents? :");
    for (; i<SIZE ; i++)
    {
        scanf("%d", &array[i]);
    }

    pthread_t t[2];

    pthread_create(&t[0], NULL, front_to_back, (void *) &SIZE );
    pthread_create(&t[1], NULL, back_to_front, (void *) &SIZE );

    pthread_join(t[0],NULL);
    pthread_join(t[1],NULL);

    free(array);

    return 0;

}

ฉันไม่เห็นปัญหาอื่นใดกับโค้ดตั้งแต่แรกเห็น

ทีนี้ ดูเหมือนว่าปัญหาของคุณคือคุณไม่เห็นความเท่าเทียมเลย คุณควรลองใช้อาเรย์ที่ใหญ่กว่า เธรดเดี่ยวอาจสามารถประมวลผลอาร์เรย์ 10 องค์ประกอบได้ก่อนที่จะสลับบริบท

อัปเดต: ฉันเพิ่งลองใช้โค้ดที่มีอาร์เรย์ 3000 องค์ประกอบ คุณสามารถเห็นพวกมันดำเนินการแบบขนานได้อย่างชัดเจน

person Filipe Gonçalves    schedule 17.05.2015
comment
คุณพูดถูก มันหนีฉันไป แต่ไม่มีการเปลี่ยนแปลง ฉันได้ผลลัพธ์เดียวกันอีกครั้ง มีเพียงเธรดเดียวเท่านั้นที่ทำงานเธรดอื่น เพียงรอรันไทม์ทั้งหมด ขอขอบคุณคำแนะนำเกี่ยวกับการจัดการข้อผิดพลาดด้วย ฉันจะทำงานเกี่ยวกับมัน - person Erol Guzoğlu; 17.05.2015
comment
@ ErolGuzoğlu ดูคำตอบที่อัปเดต 10องค์ประกอบก็ไม่มาก คุณต้องทดสอบด้วยอาร์เรย์ขนาดใหญ่เพื่อให้แต่ละเธรดไม่ทำงานเสร็จก่อนการสลับบริบท - person Filipe Gonçalves; 17.05.2015
comment
ขอบคุณสำหรับการสนับสนุน. ฉันลองโค้ดของฉันด้วยอาร์เรย์ 3000 องค์ประกอบตามที่คุณพูด ฉันเห็นว่ารหัสของฉันทำงานถูกต้อง - person Erol Guzoğlu; 17.05.2015