void *printing(void*);
pthread_mutex_t lock;
int main()
{
pthread_t thrA,thrB,thrC;
int num1=1,num2=2,num3=3;
pthread_create(&thrA, NULL,*printing,(void*)num1 );
pthread_create(&thrB, NULL,*printing, (void*)num2);
pthread_create(&thrC, NULL,*printing, (void*)num3);
pthread_join(thrA,NULL);
pthread_join(thrB,NULL);
pthread_join(thrC,NULL);
pthread_mutex_destroy (&lock);
return 0;
}
void *printing(void*param)
{
int *num; //int pointer to receive void pass
num = (int *) param; //assign void array to int array
int k;
for (k=0; k<3; k++)
{
pthread_mutex_lock (&lock);
sleep((rand() % 10)/10);
printf("%d",num);
pthread_mutex_unlock(&lock);
printf(" ");
}
pthread_exit(NULL);
}
我得到的输出是2 2 2 3 3 3 1 1 1或有时2 2 2 1 1 1 3 3 3或1 1 1 3 3 3 2 2 2
但我希望订单总是1 1 1 2 2 2 3 3 3
代码在受保护的部分(互斥锁)中休眠一些随机时间,以便下一个线程在此期间打印其编号。
问题出在哪儿?我怎样才能控制哪个线程首先运行?
答案 0 :(得分:0)
创建的第一个线程运行并获取互斥锁上的锁定,休眠,写入1然后解锁互斥锁。
输出:1
在第一个线程解锁互斥锁之前,另外两个线程运行并等待互斥锁解锁。
在第一个线程解锁互斥锁之后,等待互斥锁的另外两个线程中的一个可以获得锁定。在您的情况下,线程2获取锁定,可能是第一个开始等待互斥锁,但不保证等待线程获取锁定的顺序,请参阅Order of execution of waiting threads blocked by mutex
因此,第2个线程获取锁定,休眠,写入1并解锁互斥锁。
输出:1 1
与此同时,线程1返回到循环的开头并等待互斥锁。
在第二个线程解锁互斥锁之后,等待锁定(1和3)的另外两个线程中的一个可以立即获取它。在你的情况下,线程3获得了锁定。
因此,第3号线获得锁定,休眠,写入1并解锁互斥锁。
输出:1 1 1
依旧等等。
答案 1 :(得分:0)
首先,要么我错过了什么,要么你的问题是错的。你建议&#34;代码在受保护的部分(互斥锁)中休眠一些随机时间,以便下一个线程在那段时间打印它的号码&#34;并说你因此期望&#34; 1 2 3 ...&#34;。这是矛盾的,如果每个线程都等待其他线程,他们会轮流打印&#34; 1 1 2 2 2 2 ...&#34;正如你所说的那样。 (但那不真的是原因。)
其次,您似乎对互斥体的工作方式感到困惑。 SlappyTheFish解释得很好,所以我想我不需要打扰。但是我不确定SlappyTheFish解释的行为是否保证,即使它确实是你在测试中得到的,并且可能在实践中几乎所有情况下都会发生,但是当你使用线程时,你应该将它们视为完全独立的计算,实际上甚至可能并行运行。只有当某个线程阻塞并等待其他线程中的某些事情发生时,它才能保证该线程将运行并完成正在等待的工作。优化编译器和复杂的CPU可以对线程之间的精确执行顺序做很疯狂的事情,这样除非明确使用同步机制,否则永远不能依赖任何行为。如果我没有弄错的话,在第一个线程连续三次获得互斥锁之前,其他线程可以获得它之前也可能发生错误。您的代码未明确指定任何禁止此内容的内容。
答案 2 :(得分:0)
int k;
for (k=0; k<3; k++)
{
pthread_mutex_lock (&lock);
sleep((rand() % 10)/10);
printf("%d",num);
pthread_mutex_unlock(&lock);
printf(" ");
}
这里有两个问题。
一旦你产生线程,就无法知道它们何时,甚至以何种顺序在CPU上进行调度,系统调度程序可以自由地做任何它认为是最好的选择。因此无保证具有num = 1
的线程将是第一个被安排的线程。
你的sleep()调用是在关键部分(即锁定和解锁之间),因此线程在持有互斥锁时会睡眠,使得睡眠几乎无用,因为其他线程在睡眠时间内无法执行任何操作。一旦线程最终释放互斥锁,同一个线程就会循环并几乎立即再次调用pthread_mutex_lock()。
请注意,互斥锁并不真正用于控制线程执行顺序,它们意味着保护多个线程同时访问同一个变量。条件变量或信号量可能适合您尝试执行的操作。
您可能还想使用printf("%d\n",num)
(即添加换行符),因为I / O在大多数系统上都是缓冲的。虽然这不应该成为一个问题,但如果您试图了解正在发生的事情,可能会造成一些混乱。
这里有一些对我有用的东西(除了第一个线程不一定是第一个(见1.))
for (k=0; k<3; k++)
{
sleep(1);
pthread_mutex_lock (&lock);
printf("%d\n",num);
pthread_mutex_unlock(&lock);
}
pthread_exit(NULL);
输出: 2 1 3 2 1 3 2 1 3
再一次,这不是保证;