簡體   English   中英

如何將int作為“ void *”傳遞給線程啟動函數?

[英]How to pass an int as “void *” to thread start function?

我最初為我的斐波那契變量數組使用了一個全局變量,但發現這是不允許的。 我需要進行基本的多線程處理並處理競爭條件,但是我無法克服在pthread create中將int作為void參數的問題。 我嘗試使用沒有運氣的常量指針。 由於某些奇怪的原因,void *通過了第一個布爾測試,但在以下情況下則沒有通過else:

  $ gcc -o fibonacci fibonacci.c
    fibonacci.c:22:16: warning: comparison between pointer and integer ('void *' and 'int')
      else if (arg == 1)
               ~~~ ^  ~
    1 warning generated.

我的代碼一團糟,我真的很困惑,因為我已經重寫了很多次了。 如果將線程運行函數中的所有args轉換為int,則會得到分段錯誤11,這很有意義。 通過地址傳遞i索引並對其取消引用的所有嘗試均以失敗告終,因為它是空值,不能用作int。 你能提出其他建議嗎?

#include<stdio.h> //for printf
#include<stdlib.h>  //for malloc
#include<pthread.h> //for threading

#define SIZE 25 //number of fibonaccis to be computed
int *fibResults;  //array to store fibonacci results

void *run(void *arg)  //executes and exits each thread
{
  if (arg == 0)
  {
    fibResults[(int)arg] = 0;
    printf("The fibonacci of %d= %d\n", (int)arg, fibResults[(int)arg]);    
    pthread_exit(0); 
 }

  else if (arg == 1)
  {
    fibResults[(int)arg] = 1;
    printf("The fibonacci of %d= %d\n", (int)arg, fibResults[(int)arg]);   
    pthread_exit(0);  
  }
  else
  {
    fibResults[(int)arg] = fibResults[(int)arg -1] + fibResults[(int)arg -2];
    printf("The fibonacci of %d= %d\n", (int)arg, fibResults[(int)arg]);
    pthread_exit(0);
  }
}

//main function that drives the program.
int main()
{
  pthread_attr_t a;
  fibResults = (int*)malloc (SIZE * sizeof(int));
  pthread_attr_init(&a);  

  for (int i = 0; i < SIZE; i++)
  {
    pthread_t thread;
    pthread_create(&thread, &a, run,(void*) &i);
    printf("Thread[%d] created\t", i); 
    fflush(stdout);
    pthread_join(thread, NULL);
    printf("Thread[%d] joined & exited\t", i); 
  }
  return 0;
}

您不需要在對pthread_create()的調用中進行pthread_create()轉換-到void *的轉換是自動的。

在線程函數中,您可以使用

int i = *(int *)arg;

但是,您現在遇到了同步問題。 所有線程都使用相同的(指向相同的)整數變量,並且由於調度問題,您無法預測它們將看到哪個值。 每個線程的數據必須是“每個線程”。

因此,有多種解決方法。 在這種情況下,我可能會使用

#include <stdint.h>

並在main()

    pthread_create(&thread, &a, run, (void*)(uintptr_t)i);

然后在線程函數中:

int i = (uintptr_t)arg;

現在,必須進行演員表轉換(甚至是雙重演員表轉換)。 uintptr_tuintptr_t可以確保整數值足以容納指針。 需要強制轉換為void * ,因為沒有從任何整數類型到void *的隱式強制轉換。 這樣可以確保每個線程函數調用都具有不同的值。 共享一個指向int的指針意味着一切不受控制。

run()函數中,您應該執行以下操作:

void *run(void *ptrarg)  //executes and exits each thread
{
  int arg = *((int *)ptrarg);
  if (arg == 0)
  ....
  ....

run()其余部分中,您無需arg (int)arg替換(int)arg arg

編輯:
在創建線程時將參數傳遞給fun()可能會導致爭用情況,因為所有線程都將使用相同的指針。 檢查@Jonathan的答案以避免此問題。

@efuddy。 代替(int)arg您應該使用(int *)arg正確地轉換** void指針* void *arg

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM