Semaphore tampaknya tidak berfungsi dengan benar dengan banyak utas

Saya mencoba menulis beberapa contoh threading dengan C. Yang merupakan nomor yang didapat dari pengguna dan jumlah nomor dalam dua thread.

Benangnya berjauhan satu sama lain, depan ke belakang dan belakang ke depan.

Saya menggunakan semaphore untuk mengelola variabel global tetapi keluaran menunjukkan bahwa semaphore tidak berfungsi dengan benar.

Apa yang salah?

Keluaran kode:

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. 

Kode :

#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 sumber


Jawaban (1)


Anda harus menggunakan t[0] dan t[1] di main(): array berukuran N memiliki indeks yang valid di 0..N-1, jadi, perbaiki dulu. Berikut kode yang benar:

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);

Idealnya, Anda juga harus memeriksa apakah malloc() dan pthread_create() berhasil. Fungsi-fungsi ini dapat kembali dengan kesalahan, dan Anda harus menanganinya. Kode Anda mengabaikan kesalahan (dengan akses di luar batas, Anda sebenarnya beruntung karena kode tersebut berhasil).

Juga, mengapa Anda menggunakan semaphore seolah-olah itu adalah mutex? Semaphore tidak terlalu diperlukan di sini - bila Anda tidak membutuhkan kekuatan dan fleksibilitas semaphore, cukup gunakan mutex. Salah satu perbedaan penting adalah semaphore memungkinkan Anda menunggu di satu thread dan memposting di thread lain, sedangkan mutex harus dibuka kuncinya oleh thread yang memperolehnya.

Jadi, menggunakan semaphore yang mutexnya cukup mungkin bisa menutupi kesalahan dalam kode Anda. Jadi, saya akan melanjutkan dan menggunakan mutex saja. Berikut kode dengan semua perubahannya:

#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;

}

Saya tidak melihat masalah lain dengan kode tersebut pada pandangan pertama.

Sekarang, sepertinya masalah Anda adalah Anda tidak melihat adanya paralelisme. Anda harus mencoba dengan array yang lebih besar. Sebuah thread mungkin dapat memproses array 10 elemen sebelum peralihan konteks.

PEMBARUAN: Saya baru saja mencoba kode dengan array 3000 elemen. Anda dapat dengan jelas melihatnya dieksekusi secara paralel.

person Filipe Gonçalves    schedule 17.05.2015
comment
Anda benar, itu lolos dari saya. Tapi tidak ada perubahan. Saya mendapat hasil yang sama lagi. Hanya satu thread yang berfungsi, thread lainnya, tunggu saja sepanjang runtime. Terima kasih juga saran tentang penanganan kesalahan. Saya akan mengerjakannya. - person Erol Guzoğlu; 17.05.2015
comment
@ErolGuzoğlu Lihat jawaban yang diperbarui. 10 elemen tidak terlalu banyak. Anda perlu mengujinya dengan array besar sehingga setiap thread tidak selesai berjalan sebelum peralihan konteks. - person Filipe Gonçalves; 17.05.2015
comment
Terima kasih atas dukungannya. Saya mencoba kode saya dengan array 3000 elemen seperti yang Anda katakan. Saya dapat melihat kode saya berfungsi dengan benar. - person Erol Guzoğlu; 17.05.2015