あなただけpthread_join
は、次のコードに似た何かをすることができ、デッドロックを引き起こす可能性があることを証明したいとしている場合:
#include <stdio.h>
#include <pthread.h>
void* joinit(void* tid)
{
printf("In %#x, waiting on %#x\n", pthread_self(), (*((pthread_t*)tid)));
pthread_join((*((pthread_t*)tid)), NULL);
printf("Leaving %#x\n", pthread_self());
return NULL;
}
int main(void)
{
pthread_t thread1 = pthread_self();
pthread_t thread2;
pthread_create(&thread2, NULL, joinit, &thread1);
joinit(&thread2);
return 0;
}
これは、生成されたスレッド上で待機するようにメインスレッドの原因となりますし、あなたが実証しようとしているものを混乱させる余分なロックプリミティブを必要とせずに、メインスレッド上で待機する(生成されたデッドロックを保証する)生成されたスレッド。
そして、もっと直接ご質問のいくつかに答えるために:
をthread1
ためpthread_create
が呼び出されたときthread2
がまだ指定されていないので、それはEINVAL '(不正な引数)と言います。
...とコメントの一つから...
私はこれを試してみました、それが働いていたが、問題は、ある時々私は再びEINVALを取得するので、それが唯一のSOMETIMES動作します。あなたのコードで
、あなたは2つのスレッド産卵する連続pthread_create
を呼び出す:あなたは上で参加することで渡されたスレッドハンドルをつかみ、あなたのjoinit
コードで
pthread_create(&thread1, NULL, joinit, &thread2);
pthread_create(&thread2, NULL, joinit, &thread1);
を:
pthread_t* tid_c = (pthread_t*)tid;
int retval = pthread_join(*tid_c, NULL);
このの場合はとなり、それ以外の場合はEINVAL
となり、理由はそれぞれtime slicesとなります文脈とsequencing。最初のpthread_create
が呼び出されたときにはthread1
への有効なハンドルが返されますが、少なくともthread2
へのハンドルは有効ではありません。少なくとも2番目のpthread_create
が呼び出されるまで有効ではありません。
これは、スレッドが作成されると、返されたスレッドハンドルが有効であるにもかかわらず、スレッドが実際に動作していることを意味します。このような場合、1つのスレッドが「予想される」より多くのコードを実行する可能性があります。あなたのコードでは、両方のpthread_create
機能はそれぞれが有効なハンドルを指すようにtid_c
を可能pthread_join
文を打つ前に、スレッドの十分な「時間」を生み出し与えることができるメインスレッドに割り当てられたタイムスライスに呼び出されたことが起こるかもしれません。 EINVAL
の場合、pthread_create(&thread1, NULL, joinit, &thread2)
が呼び出され、pthread_create(&thread2, NULL, joinit, &thread1)
が有効なハンドル(エラーを引き起こす)を与える前に、生成されたスレッドはpthread_join(*tid_c, NULL)
に達しました。
あなたが今どのように似たコードを維持したい場合は、スレッドが途中で何かを終了するか、呼び出していないことを確認するために、ある種のロックを追加する必要があります。
#include <stdio.h>
#include <pthread.h>
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
void* joinit(void* tid)
{
/* this can be above the lock because it will be valid after lock is acquired */
pthread_t* tid_c = (pthread_t*)tid;
int retval = -1;
pthread_mutex_lock(&lock);
pthread_mutex_unlock(&lock);
printf("%#x waiting on %#x\n", pthread_self(), *tid_c);
retval = pthread_join(*tid_c, NULL);
printf("In joinit: tid = %d, retval = %d \n", *tid_c, retval);
return NULL;
}
int main()
{
pthread_t thread1;
pthread_t thread2;
/* get the lock in the main thread FIRST */
pthread_mutex_lock(&lock);
pthread_create(&thread1, NULL, joinit, &thread2);
pthread_create(&thread2, NULL, joinit, &thread1);
/* by this point, both handles are "joinable", so unlock */
pthread_mutex_unlock(&lock);
/* can wait on either thread, but must wait on one so main thread doesn't exit */
pthread_join(thread2, NULL);
return 0;
}
・ホープ、この助けられる。
私はこれを試してみました、それが働いていたが、問題は時々、私は再びEIVALを取得するので、それが唯一のSOMETIMES作品です。 私はメソッドjoinitでerrnoをチェックしています! –
はい、スレッドが開始された時点を決定することはできませんが、OSはそれを行います。 –
はい、わかっています。私は信頼できるデッドロック状況が必要です。 –