在 pthread_create 中使用时参数会损坏
Arguments become corrupt when used in pthread_create
我正在尝试学习多线程,我认为并行化算法是一个很好的练习。 Quicksort and Merge sort 特别是。
我的问题是参数从调用 pthread_create
到进入与调用关联的函数的过程中损坏。
我的快速排序函数如下所示
static void* quick_sort( void* threadData )
{
struct ThreadData* data = (struct ThreadData*)threadData;
unsigned pivot_index;
pthread_mutex_lock( &lock );
printf( "\nThread %d : Entering quick_sort with low = %d, high = %d ", data->threadID, data->low, data->high );
pthread_mutex_unlock( &lock );
// No need to sort a vector of zero or one element
if ( data->low >= data->high )
return NULL;
// Select the pivot value
pivot_index = ( data->low + data->high ) / 2;
// Partition the vector
pivot_index = partition( data->collection, data->low, data->high, pivot_index );
/* Set thread data */
//-------------------------------------------------
struct ThreadData left, right;
left.collection = data->collection;
left.low = data->low;
left.high = pivot_index - 1;
left.threadID = data->threadID;
right.collection = data->collection;
right.low = pivot_index + 1;
right.high = data->high;
right.threadID = data->threadID;
//------------------------------------------------
/* sort the two sub arrays */
if ( data->low < pivot_index )
{
pthread_mutex_lock( &lock ); // Lock mutex
if( numRunningThreads < NUM_THREADS ) // Check for an available thread
{
// Find available thread index
int j;
for( j = 0; j < NUM_THREADS; j++ )
{
if( !runningThreads[j] )
{
left.threadID = j; // threadPool[j] is available
runningThreads[j] = true; // Set thread as running
break;
}
}
/* Use mutex lock when incrementing numRunningThreads
since it is a global variable and shared by all threads */
numRunningThreads++;
printf( "\n Dispatching thread %d -- ", j );
printf( "low = %d, high = %d, pivot_index = %d, threadID = %d ---", left.low, left.high, pivot_index, left.threadID );
printf( " %d threads running", numRunningThreads );
pthread_mutex_unlock( &lock );
// Create new thread
pthread_create( &threadPool[left.threadID], NULL, &quick_sort, (void*)&left );
}
else
{
// There are NO available threads
pthread_mutex_unlock( &lock );
quick_sort( (void*)&left ); // Use existing thread
}
}
if ( pivot_index < data->high )
quick_sort( (void*)&right );
return NULL;
}
编辑
´pthread_create´的用法是
pthread_create( &threadPool[left.threadID], NULL, &quick_sort, (void*)&left );
该函数最初是从 main
:
调用的
// Use first thread in threadPool
runningThreads[0] = true;
numRunningThreads++;
pthread_create( &threadPool[0], NULL, &quick_sort, (void*)&threadData );
// Join threads
for( i = 0; i < NUM_THREADS; i++ )
{
if( runningThreads[i] )
{
pthread_join( threadPool[i], NULL );
pthread_mutex_lock( &lock );
printf( "\nJoining thread %d", i );
runningThreads[i] = false;
numRunningThreads--;
pthread_mutex_unlock( &lock );
}
}
根据输出,输入函数时数据已损坏
Thread 3 : Entering quick_sort with low = -259450448, high = 32567
对我做错了什么有什么想法吗?
在线程中定义并初始化了一个自动变量left
:
struct ThreadData left, right;
然后在特定条件下该变量被传递给新创建的线程。这不是在任何类型的锁定机制下完成的:
pthread_create( &threadPool[left.threadID], NULL, &quick_sort, (void*)&left );
创建该线程并向其传递left
后,当前线程可以立即退出,同时创建的线程仍在运行并使用变量left
:
if ( pivot_index < data->high )
quick_sort( (void*)&right );
return NULL;
然后变量 left
停止存在,但仍在使用,导致未定义的行为。
解决方案是使用分配的变量,即使用malloc,将这些变量传递给创建的线程,并在不再使用时释放它们。
我正在尝试学习多线程,我认为并行化算法是一个很好的练习。 Quicksort and Merge sort 特别是。
我的问题是参数从调用 pthread_create
到进入与调用关联的函数的过程中损坏。
我的快速排序函数如下所示
static void* quick_sort( void* threadData )
{
struct ThreadData* data = (struct ThreadData*)threadData;
unsigned pivot_index;
pthread_mutex_lock( &lock );
printf( "\nThread %d : Entering quick_sort with low = %d, high = %d ", data->threadID, data->low, data->high );
pthread_mutex_unlock( &lock );
// No need to sort a vector of zero or one element
if ( data->low >= data->high )
return NULL;
// Select the pivot value
pivot_index = ( data->low + data->high ) / 2;
// Partition the vector
pivot_index = partition( data->collection, data->low, data->high, pivot_index );
/* Set thread data */
//-------------------------------------------------
struct ThreadData left, right;
left.collection = data->collection;
left.low = data->low;
left.high = pivot_index - 1;
left.threadID = data->threadID;
right.collection = data->collection;
right.low = pivot_index + 1;
right.high = data->high;
right.threadID = data->threadID;
//------------------------------------------------
/* sort the two sub arrays */
if ( data->low < pivot_index )
{
pthread_mutex_lock( &lock ); // Lock mutex
if( numRunningThreads < NUM_THREADS ) // Check for an available thread
{
// Find available thread index
int j;
for( j = 0; j < NUM_THREADS; j++ )
{
if( !runningThreads[j] )
{
left.threadID = j; // threadPool[j] is available
runningThreads[j] = true; // Set thread as running
break;
}
}
/* Use mutex lock when incrementing numRunningThreads
since it is a global variable and shared by all threads */
numRunningThreads++;
printf( "\n Dispatching thread %d -- ", j );
printf( "low = %d, high = %d, pivot_index = %d, threadID = %d ---", left.low, left.high, pivot_index, left.threadID );
printf( " %d threads running", numRunningThreads );
pthread_mutex_unlock( &lock );
// Create new thread
pthread_create( &threadPool[left.threadID], NULL, &quick_sort, (void*)&left );
}
else
{
// There are NO available threads
pthread_mutex_unlock( &lock );
quick_sort( (void*)&left ); // Use existing thread
}
}
if ( pivot_index < data->high )
quick_sort( (void*)&right );
return NULL;
}
编辑
´pthread_create´的用法是
pthread_create( &threadPool[left.threadID], NULL, &quick_sort, (void*)&left );
该函数最初是从 main
:
// Use first thread in threadPool
runningThreads[0] = true;
numRunningThreads++;
pthread_create( &threadPool[0], NULL, &quick_sort, (void*)&threadData );
// Join threads
for( i = 0; i < NUM_THREADS; i++ )
{
if( runningThreads[i] )
{
pthread_join( threadPool[i], NULL );
pthread_mutex_lock( &lock );
printf( "\nJoining thread %d", i );
runningThreads[i] = false;
numRunningThreads--;
pthread_mutex_unlock( &lock );
}
}
根据输出,输入函数时数据已损坏
Thread 3 : Entering quick_sort with low = -259450448, high = 32567
对我做错了什么有什么想法吗?
在线程中定义并初始化了一个自动变量left
:
struct ThreadData left, right;
然后在特定条件下该变量被传递给新创建的线程。这不是在任何类型的锁定机制下完成的:
pthread_create( &threadPool[left.threadID], NULL, &quick_sort, (void*)&left );
创建该线程并向其传递left
后,当前线程可以立即退出,同时创建的线程仍在运行并使用变量left
:
if ( pivot_index < data->high )
quick_sort( (void*)&right );
return NULL;
然后变量 left
停止存在,但仍在使用,导致未定义的行为。
解决方案是使用分配的变量,即使用malloc,将这些变量传递给创建的线程,并在不再使用时释放它们。