web-dev-qa-db-ja.com

pthread_createおよび最後の引数として整数を渡す

次の機能があります。

_void *foo(void *i) {
    int a = (int) i;
}

int main() {
    pthread_t thread;
    int i;
    pthread_create(&thread, 0, foo, (void *) i);
}
_

コンパイル時に、キャストに関するいくつかのエラーがあります(_(void *) i_およびint a = (int) i)。 _pthread_create_の最後の引数として整数を正しく渡すにはどうすればよいですか?

31
Gradient

Szxの答えに基づいて(だから彼に信用を与えて)、これがforループでどのように機能するかを以下に示します。

_void *foo(void *i) {
    int a = *((int *) i);
    free(i);
}

int main() {
    pthread_t thread;
    for ( int i = 0; i < 10; ++1 ) {
        int *arg = malloc(sizeof(*arg));
        if ( arg == NULL ) {
            fprintf(stderr, "Couldn't allocate memory for thread arg.\n");
            exit(EXIT_FAILURE);
        }

        *arg = i;
        pthread_create(&thread, 0, foo, arg);
    }

    /*  Wait for threads, etc  */

    return 0;
}
_

ループの各反復で、それぞれが異なるアドレスを持つ新しいメモリを割り当てているため、各反復でpthread_create()に渡されるものは異なるため、どのスレッドもアクセスしようとしません。同じメモリで、iのアドレスを渡した場合のようにスレッドセーフの問題は発生しません。この場合、配列を設定し、要素のアドレスを渡すこともできます。

36
Paul Griffiths

ヒープにintを割り当てて、pthread_create()に渡すことができます。その後、スレッド関数で割り当てを解除できます。

void *foo(void *i) {
    int a = *((int *) i);
    free(i);
}

int main() {
    pthread_t thread;
    int *i = malloc(sizeof(*i));
    pthread_create(&thread, 0, foo, (void *) i);
}
21
szx

Pthread_create()の最後の引数にiのアドレス(現在のiの値ではなく)をキャストする必要があります。

_pthread_create(&thread, 0, foo, (void *) &i);
                                         ^  is missing
_

そして、あなたの関数でもキャストが間違っています。そのはず:

_int a = *((int*) i);
_
  1. 読み取り値を使用する場合は、iも初期化されていないmain()の値に初期化する必要があります。

2 main()に適切な定義を使用します。

_ int main(void) 
_

またはint main(int argc, char *argv[])またはその同等物。

10
P.P.

古い質問ですが、私は今日同じ問題に直面し、この道に従わないことにしました。私のアプリケーションは本当にパフォーマンスに関するものだったので、intsのこの配列を静的に宣言することにしました。

pthread_join/pthread_cancelpthread_createとは別のスコープにあるアプリケーションをあまり知らないので、この方法を選択しました。

#define NB_THREADS 4

void *job(void *_i) {
  unsigned int i = *((unsigned int *) _i);
}

int main () {
  unsigned int ints[NB_THREADS];
  pthread_t    threads[NB_THREADS];
  for (unsigned int i = 0; i < NB_THREADS; ++i) {
    ints[i] = i;
    pthread_create(&threads[i], NULL, job, &ints[i]);
  }
}

私はそれがよりエレガントで、より効率的であり、このスコープ内にのみ存在するため、解放について心配する必要はありません。

6
Jerska

これは古い質問ですが、必要なのは記述子のような正の整数を渡すことだけです。アドレスとして直接渡すことができますが、ハックはうまく機能し、割り当てを避けることができます:)

注:整数のサイズはOSのポインターのサイズと一致する必要がありますが、現在ではほとんどのシステムはネイティブ64ビットです。

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

void *_thread_loop(void *p)
{
  uint64_t n = (uint64_t)p;

  printf("received %llu\n", n);

  return NULL;
}



int main(int argc, char const *argv[])
{
  pthread_t read_thread_id;
  uint64_t n = 42;
  pthread_create(&read_thread_id, NULL, _thread_loop, (void *)n);

  pthread_join(read_thread_id, NULL);
  return 0;
}
0
Schmurfy