如何保护共享资源?需要确定使用共享资源并保护它们的代码行。我的猜测是pop和push资源是共享的。因此,为了保护它们,我会将这些功能放在一个保护标签下:就像有private:和public :?还有如何使我创建的200个线程共享同一堆栈。更新:我的教授说top是共享资源。
/*
* Stack containing race conditions
*/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
// Linked list node
typedef int value_t;
typedef struct Node
{
value_t data;
struct Node *next;
} StackNode;
// Stack function declarations
void push(value_t v, StackNode **top);
value_t pop(StackNode **top);
int is_empty(StackNode *top);
pthread_mutex_t mutex;
//--Tom This is the wrong function signature for thread entry functions
void *testStack(void *arg)
{
StackNode *top = NULL;
for (int i = 0; i < 500; i++)
{
pthread_mutex_lock(&mutex);
// --Tom Mix these up a bit more
push(5, &top);
pop(&top);
push(6, &top);
pop(&top);
push(15, &top);
pop(&top);
pthread_mutex_unlock(&mutex);
}
pthread_exit(0);
}
int main(int argc, char *argv[])
{
//--Tom defining mutex on the stack is not a good choice. Threads don't share data on the stack
pthread_mutex_init(&mutex, NULL);
for (int i = 0; i < 200; i++)
{
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
//--Tom this is the wrong place to lock. Need something that sourounds only the code accessing shared resources
//--Tom argv[1] in not what yo want to pass the thread
pthread_create(&tid, &attr, testStack, NULL);
//--Tom You are not allowingthe threads to run in parallel
}
return 0;
}
// Stack function definitions
void push(value_t v, StackNode **top)
{
//--Tom you have not identified the critical lines of code and protected them
StackNode *new_node = malloc(sizeof(StackNode));
new_node->data = v;
new_node->next = *top;
*top = new_node;
}
value_t pop(StackNode **top)
{
//--Tom you have not identified the critical lines of code and protected them
if (is_empty(*top))
return (value_t)0;
value_t data = (*top)->data;
StackNode *temp = *top;
*top = (*top)->next;
free(temp);
return data;
}
int is_empty(StackNode *top)
{
//--Tom you have not identified the critical lines of code and protected them
if (top == NULL)
return 1;
else
return 0;
}
答案 0 :(得分:1)
如何使创建的200个线程共享同一堆栈
第一种可能性是拥有一个全局变量StackNode *top;
,但是如果您想将相同的代码重用于不同的堆栈,则会出现问题。
第二个方法是,在启动新线程代替 NULL 时,在 main 中将该变量设置为local,并在参数中提供其 address 。 em>您当前拥有的,那么 testStack 的 arg 实际上是 StackNode **
请勿在调用 push / pop 之前/之后管理互斥锁,而是在函数内部对其进行管理,否则很有可能忘记保护。因此,mutext不会出现在 testStack 中。在这种情况下,请参阅我对is_empty
int is_empty(StackNode *top)
{
//--Tom you have not identified the critical lines of code and protected them
if (top == NULL)
return 1;
else
return 0;
}
为什么这么复杂?
int is_empty(StackNode *top)
{
//--Tom you have not identified the critical lines of code and protected them
return (top == NULL);
}
是的,堆栈没有被修改,也没有在内部看,所以对于空的观点来说,并不是唯一的 ,所以警告:
/* ptop is a StackNode ** */
if (!is_empty(*ptop))
// here the stack can be empty anyway because an other thread got the CPU
pop(ptop);
如果您想提供一个可以执行多个操作的保护区域,则必须使用相同的 mutex (可能被功能 regionEnter 和 regionExit隐藏) ),并且由于 mutex 也需要递归(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
)
将 mutex 分组和 top 分组到另一个结构中可能会很有趣,这使得不能为不同的堆栈共享互斥体