Linux 读取变量会把事情搞砸吗?

Linux 读取变量会把事情搞砸吗?,linux,multithreading,printf,Linux,Multithreading,Printf,我们有以下代码行: printf("%d\n", toc->runlist.next); printf("%d\n", toc->runlist.next); 以下是定义: typedef struct thread_overview_control{ int id[NR_UTHREADS]; list_t runlist; int active_counter; int main_thread; int need_resched; } th

我们有以下代码行:

printf("%d\n", toc->runlist.next);
printf("%d\n", toc->runlist.next);
以下是定义:

typedef struct thread_overview_control{
    int id[NR_UTHREADS];
    list_t runlist;
    int active_counter;
    int main_thread;
    int need_resched;
} thread_overview_control;

thread_overview_control* toc;
我要做的是实现用户线程。出于某种原因,上述代码在测试运行崩溃点的输出是:

12345678  //some address
0         //NOW IT'S NULL?!?!?!
这怎么可能发生??我们所做的就是读取一个变量。
奇怪的是,没有printf就不会有崩溃。发生了什么?

很可能另一个线程正在访问(并更改)两次调用printf()之间的变量。如果删除printf语句,则计时会改变,行为也会不同


如果数据确实被多个线程访问,则需要使用互斥锁对其进行保护。

什么是
list\t
?这是普通的C吗?请注意,C++中可以(排序),以便调用<代码>运行列表。NeX//CODE实际上调用一些方法,它可能是伪装的一些迭代器。 不过,Vicky的答案对我来说似乎更有可能。

printf()
并没有修改它的可变参数。但是,
printf()
是一种成本足够高的操作,可以公开线程之间没有(或不正确)锁定导致的争用

您要使用的是互斥锁:

pthread_mutex_t thread_lock = PTHREAD_MUTEX_INITIALIZER;

void *thread_func(void *threadarg)
{
    thread_overview_control *toc = (thread_overview_control *)threadarg;

    pthread_mutex_lock(&thread_lock);
    printf("%d\n", toc->runlist.next);
    printf("%d\n", toc->runlist.next);
    pthread_mutex_unlock(&thread_lock);

    ....
在该示例中,
pthread\u mutex\u lock()
将在另一个线程拥有锁时阻塞。如果函数在等待锁可用时可以执行其他有用的工作,请尝试
pthread\u mutex\u trylock()
,可能是在
while()
循环中

只需确保每个线程都可以访问互斥体,方法是将其设置为全局(或将其置于每个线程都可以访问的结构中)。同样重要的是,使用
PTHREAD\u mutex\u初始值设定项来初始化互斥锁,否则可能会在没有任何线程实际持有锁的情况下导致锁被持有


无论何时读取或写入
*toc
,都需要获取锁。

尝试在valgrind下运行程序。它将指出您可能存在的任何与内存相关的错误。

尽管竞争条件是一个可能的原因,但听起来您的问题比我预期的解释更加一致


另一种可能是一个普通的老野性指针。您是如何初始化toc的?如果它最终指向释放的堆栈内存,那么第一个
printf()
调用可以很容易地对其进行踩踏。

您的意思是,如果您只调用toc->runlist.next toc->runlist.next,则不会发生崩溃?那么:int-someint-someint=toc->runlist.next-someint=toc->runlist.next也会产生崩溃吗?但是如果这两个
printf
s真的是一个接一个,那么发生这种情况的概率很低。。。