因此,我有一个程序,该程序具有2个线程,可将变量从0递增到100,并且工作正常。
#include<stdio.h>
#include<stdlib.h>
#include<semaphore.h>
#include<pthread.h>
int contor;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void *incrementare(void *args) {
int id = (int)args;
while(1) {
pthread_mutex_lock(&mutex);
if (contor >= 100) {
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
while (contor %2 == id) {
pthread_cond_wait(&cond,&mutex);
}
contor++;
printf("Thread %d increment: %d\n",id,contor);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
}
int main(void) {
pthread_t th1, th2,th3;
if(pthread_create(&th1, NULL, &incrementare, (void *)0) < 0) {
perror("Error!\n");
exit(1);
}
if(pthread_create(&th2, NULL, &incrementare, (void *)1) < 0) {
perror("Error!\n");
exit(2);
}
pthread_join(th1, NULL);
pthread_join(th2, NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
return 0;
}
结果是这样的:
Thread 1 increment: 1
Thread 0 increment: 2
Thread 1 increment: 3
Thread 0 increment: 4
Thread 1 increment: 5
Thread 0 incre.. and so on ,which is nice.
但是问题是当我尝试使用3个线程时,它不再起作用,因为它们随后随机出现。我只进行了3次更改,但不知道问题出在哪里。
#include<stdio.h>
#include<stdlib.h>
#include<semaphore.h>
#include<pthread.h>
int contor;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void *incrementare(void *args) {
int id = (int)args;
while(1) {
pthread_mutex_lock(&mutex);
if (contor >= 100) {
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
while (contor %3 == id) {
pthread_cond_wait(&cond,&mutex);
}
contor++;
printf("Thread %d increment: %d\n",id,contor);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
}
int main(void) {
pthread_t th1, th2,th3;
if(pthread_create(&th1, NULL, &incrementare, (void *)0) < 0) {
perror("Error!\n");
exit(1);
}
if(pthread_create(&th2, NULL, &incrementare, (void *)1) < 0) {
perror("Error!\n");
exit(2);
}
if(pthread_create(&th3, NULL, &incrementare, (void *)2) < 0) {
perror("Error!\n");
exit(3);
}
pthread_join(th1, NULL);
pthread_join(th2, NULL);
pthread_join(th3, NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
return 0;
}
它应该做同样的权利吗?现在只有3个。为什么不起作用?这是这样的
Thread 2 increment: 1
Thread 2 increment: 2
Thread 1 increment: 3
Thread 1 increment: 4
Thread 2 increment: 5
Thread 1 increment: 6
如果你想线程以保证循环,你需要做一个线程等待,直到模N计数器(线程数)是一个特定的ID,直到它是什么,但那个特定的ID。有两个id,如果不是一个,则必须是另一个。但是对于三个,有两个中断的情况,一个等待的情况。调度程序可以自由选择要释放的两个备用线程中的任何一个。
但是,如果您更改此设置:
while (contor %3 == id)
对此:
while (contor %3 != id)
您将强制给定线程仅写入以其id为模的值。
但是,这还不够。您还需要唤醒所有服务员。以前,当您只有两个线程时,总是有相同的服务员:不是活动线程的“另一个人”。这pthread_cond_signal
将被定向到特定的目标线程(唯一一个未运行的线程),并且自然也是下一个线程。
如果使用三个或更多线程,则pthread_cond_signal
可能被唤醒的单线程可能不是具有扭曲模N id的线程。实际上,您拥有的线程越多,发生这种情况的可能性就越大。在这种情况下,线程将返回等待状态,但没有其他等待状态会再次启动。您不想让这个碰碰运气。确保所有服务员都醒了,以确保下一个服务员能够收到信号。
千万不能仅通过发送另一个解决这个问题pthread_cond_signal
的地方。而是发送广播:更改此内容:
pthread_cond_signal(&cond);
对此:
pthread_cond_broadcast(&cond);
这将确保所有正在等待的线程最终都能看清楚,contor
并且与contor
N模匹配的线程将有机会碰碰,打印,发送下一个广播,然后回到等待状态。
因此,对代码的最小更改是:
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h> // added for intptr_t
#include<inttypes.h> // added for printf formatter for intptr_t
#include<pthread.h>
int contor;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void *incrementare(void *args) {
intptr_t id = (intptr_t)args; // proper way to pass an integer via thread param
while(1) {
pthread_mutex_lock(&mutex);
if (contor >= 100) {
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
while (contor %3 != id) {
pthread_cond_wait(&cond,&mutex);
}
contor++;
printf("Thread %"PRIdPTR " increment: %d\n",id,contor);
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
}
return NULL; // should always have well-defined return value
}
int main(void) {
pthread_t th1, th2,th3;
if(pthread_create(&th1, NULL, &incrementare, (void *)0) < 0) {
perror("Error!\n");
exit(1);
}
if(pthread_create(&th2, NULL, &incrementare, (void *)1) < 0) {
perror("Error!\n");
exit(2);
}
if(pthread_create(&th3, NULL, &incrementare, (void *)2) < 0) {
perror("Error!\n");
exit(3);
}
pthread_join(th1, NULL);
pthread_join(th2, NULL);
pthread_join(th3, NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
return 0;
}
结果如下:
Thread 0 increment: 1
Thread 1 increment: 2
Thread 2 increment: 3
Thread 0 increment: 4
Thread 1 increment: 5
Thread 2 increment: 6
Thread 0 increment: 7
Thread 1 increment: 8
Thread 2 increment: 9
Thread 0 increment: 10
....
Thread 0 increment: 97
Thread 1 increment: 98
Thread 2 increment: 99
Thread 0 increment: 100
Thread 1 increment: 101
Thread 2 increment: 102
额外的两个输出是因为代码检查的天花板休息条件是之前的CVaR的-谓词环路。应该在之后,但是我留给您解决。
但是请记住,这样做最终会破坏在任务上松开多个线程的目的。理想情况下,您希望任何可用线程来执行工作。您的工作只影响单个全局变量,这在一定程度上破坏了线程的真正目的(显然,您不会使用线程计数到100;因此,在循环中使用单个线程是理想的选择)。
无论如何,程序的压缩版本将显示在下面。更改的值N_THREADS
,并N_COUNT
看到输出的差异。
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <pthread.h>
#define N_THREADS 7
#define N_COUNT 100
int contor; // 0
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void *incrementare(void *args)
{
intptr_t id = (intptr_t)args;
pthread_mutex_lock(&mutex);
while(1)
{
while (contor < N_COUNT && contor % N_THREADS != id)
pthread_cond_wait(&cond, &mutex);
if (contor == N_COUNT)
break;
printf("Thread %"PRIdPTR" increment: %d\n", id, ++contor);
pthread_cond_broadcast(&cond);
}
pthread_mutex_unlock(&mutex);
return NULL;
}
int main(void)
{
pthread_t ar[N_THREADS];
intptr_t id = 0;
for (int i=0; i<N_THREADS; ++i)
{
if(pthread_create(ar+i, NULL, &incrementare, (void *)id++) < 0) {
perror("Error!\n");
exit(1);
}
}
for (int i=0; i<N_THREADS; ++i)
pthread_join(ar[i], NULL);
return 0;
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句