所以这是我的情景。首先,我有一个结构 -
struct interval
{
double lower;
double higher;
}
现在我的线程功能 -
void* thread_function(void* i)
{
interval* in = (interval*)i;
double a = in->lower;
cout << a;
pthread_exit(NULL)
}
主要是,假设我创建了这两个主题 -
pthread_t one,two;
interval i;
i.lower = 0; i.higher = 5;
pthread_create(&one,NULL,thread_function,&i);
i.lower=10; i.higher = 20;
pthread_create(&two,NULL,thread_function, &i);
pthread_join(one,NULL);
pthread_join(two,NULL);
这是问题所在。理想情况下,线程“one”应打印出0,线程“two”应打印出10.然而,这不会发生。偶尔,我最终会得到两个10秒。
这是设计的吗?换句话说,在创建线程时,i.lower中的值已经在main中更改,因此两个线程最终都使用相同的值?
答案 0 :(得分:3)
这是设计吗?
是。当线程准确启动以及何时访问该值时,未指定。您需要为每个人提供他们自己的数据副本。
答案 1 :(得分:3)
您的申请是不确定的 没有人知道什么时候会安排一个线程运行。
注意:通过创建线程并不意味着它将立即(甚至首先)开始执行。创建的第二个线程实际上可能在第一个线程之前开始运行(它完全取决于操作系统和硬件)。
要获得确定性行为,必须为每个线程提供自己的数据(主线程不会对其进行修改)。
pthread_t one,two;
interval oneData,twoData
oneData.lower = 0; oneData.higher = 5;
pthread_create(&one,NULL,thread_function,&oneData);
twoData.lower=10; twoData.higher = 20;
pthread_create(&two,NULL,thread_function, &twoData);
pthread_join(one,NULL);
pthread_join(two,NULL);
我不会在设计上称之为。
我宁愿将其称为调度策略的副作用。但观察到的行为是我所期待的。
答案 2 :(得分:1)
这是经典的“竞争条件”;结果取决于哪个线程赢得“比赛”。你无法知道哪个线程每次都会“赢”。
答案 3 :(得分:1)
您对问题的分析是正确的;你根本没有任何保证,在主函数的下一行更改数据之前,创建的第一个线程将能够读取i.lower。从某种意义上说,这就是为什么一开始很难想到多线程编程的原因。
直接问题的直接解决方案是使用不同的数据保持不同的间隔,并将单独的数据传递给每个线程,即
interval i, j;
i.lower = 0; j.lower = 10;
pthread_create(&one,NULL,thread_function,&i);
pthread_create(&two,NULL,thread_function,&j);
这当然会解决您的直接问题。但很快你可能想知道如果你想要多个线程实际使用相同的数据该怎么办。如果线程1想要对i进行更改并且线程2想要考虑这些,该怎么办?如果每个线程必须将其内存与其他线程分开(好吧,暂时将消息传递出图片),那么进行多线程编程几乎没什么意义。输入互斥锁!我想我会给你一个提示,你要尽快看看这个主题,因为它也会帮助你理解一般线程的基础知识以及多线程所需的心态变化编程。
我似乎记得this是对pthreads的一个不错的简短介绍,包括开始理解锁定等。