全局计数器和并发线程。如何检查计数器进度?

huangapple go评论66阅读模式
英文:

Global counters and concurrent threads. How to check counter progress?

问题

我试图编写一个简单的程序来理解线程。我希望每个线程递增一个名为 'counter' 的全局变量到 4 百万。每个线程只计数到 2 百万。我在每个函数的结尾放置了一个打印语句,以查看函数完成时迭代了多少次以及全局计数器的位置。但是 thread1Func 中的全局计数器总是非常高,像是 380 万 - 390 万,然后在 thread2Func 中,计数器总是 400 万(如预期的那样)。

我这样做对吗?thread1Func 总是打印出 'counter' 的这么高的值有原因吗?我想象它应该在 200 万到 400 万之间更平均一些。任何建议将不胜感激!

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

#define MAX 2000000UL
pthread_mutex_t lock;

struct shared_data
{
    int value; /* 用于存储结果的共享变量 */
};

struct shared_data *counter;

void *thread1Func(void *tid)
{
    uint32_t i = 0;
    while (i < MAX)
    {

        if (pthread_mutex_trylock(&lock) == 0)
        {
            counter->value++;
            pthread_mutex_unlock(&lock);
            i++;
        }
    }
    printf("我是线程 1。我计数了 %d 次。全局计数器 = %d\n", i, counter->value);
    return NULL;
}

void *thread2Func(void *tid)
{
    uint32_t i = 0;
    while (i < MAX)
    {

        if (pthread_mutex_trylock(&lock) == 0)
        {
            counter->value++;
            pthread_mutex_unlock(&lock);
            i++;
        }
    }
    printf("我是线程 2。我计数了 %d 次。全局计数器 = %d\n", i, counter->value);
    return NULL;
}

int main()
{

    counter = (struct shared_data *)malloc(sizeof(struct shared_data));
    printf("初始计数器值:%d\n", counter->value);

    pthread_t thread1;
    pthread_t thread2;
    pthread_mutex_init(&lock, NULL);

    pthread_create(&thread1, NULL, thread1Func, NULL);
    pthread_create(&thread2, NULL, thread2Func, NULL);

    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    printf("最终计数器:%d\n", counter->value);
    return 0;
}
英文:

I am trying to write a simple program to understand threads. I want each thread to increment a global variable 'counter' to 4 million. Each thread only counts to 2 million. I placed a print statement at the end of each function to see how many iterations and where the global counter is at upon completion of the function. But the global counter in thread1Func is always very high, like 3.8 - 3.9 million, and then in thread2Func the counter is always 4 mil (as expected).

Am I doing this correctly? Is there a reason thread1Func is always printing such a high value for 'counter'? I would imagine it should be somewhere between 2 mil - 4 mil more evenly. Any advice would be greatly appreciated!

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;unistd.h&gt;
#include &lt;pthread.h&gt;


#define MAX 2000000UL
pthread_mutex_t lock;
//pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

struct shared_data
{
    int value;     /* shared variable to store result*/
    
};

struct shared_data  *counter;


void* thread1Func(void * tid){
    uint32_t i = 0;
    while(i &lt; MAX){
        
        if(pthread_mutex_trylock(&amp;lock) == 0){
            counter-&gt;value++;
            pthread_mutex_unlock(&amp;lock);
            i++;
        }
    }
    printf(&quot;I am thread 1. I counted %d times. Global counter = %d\n&quot;, i, counter-&gt;value);
    return NULL;
}

void* thread2Func(void * tid){
    
    uint32_t i = 0;
    while(i &lt; MAX){
        
        if(pthread_mutex_trylock(&amp;lock) == 0){
            counter-&gt;value++;
            pthread_mutex_unlock(&amp;lock);
            i++;
        }

    }
    printf(&quot;I am thread 2. I counted %d times. Global counter = %d\n&quot;, i, counter-&gt;value);
    return NULL;
}


int main() {
    
    counter = (struct shared_data *) malloc(sizeof(struct shared_data));
    printf(&quot;Initial Counter Value: %d\n&quot;, counter-&gt;value);
    
    pthread_t thread1;
    pthread_t thread2;
    pthread_mutex_init(&amp;lock, NULL);
    
    pthread_create(&amp;thread1, NULL, thread1Func, NULL);
    pthread_create(&amp;thread2, NULL, thread2Func, NULL);
    
    
    pthread_join(thread1,NULL);
    pthread_join(thread2,NULL);
    
    
    printf(&quot;Final Counter: %d\n&quot;, counter-&gt;value);
    return 0;
}

答案1

得分: 0

在thread1Func中,全局计数器始终非常高,如380万到390万,然后在thread2Func中,计数器始终为400万。

这不足为奇。如果两个线程大致以相同的速度工作,那么当第一个线程完成时,第二个线程应该几乎也快要完成了。第一个线程在这一点上已经将它的两百万添加到全局计数器中,然后第二个线程已经添加了差不多两百万。当第一个线程完成时,你完全可以期望全局计数器接近400万。

唯一的情况是,如果第一个线程在第二个线程开始工作之前就已经完成,它才会打印两百万。

英文:

> the global counter in thread1Func is always very high, like 3.8 - 3.9 million, and then in thread2Func the counter is always 4 mil

That is no surprise. If both threads are working at roughly the same speed, then when the first thread finishes, the second thread should be very nearly finished too. The first thread at that point has added its two million to the global counter, and then second thread already will have added almost two million of its own. You should totally expect the global counter to be almost four million when the first thread finishes.

The only way the first thread could print two million is if the first thread is finished before the second thread has begun to work.

答案2

得分: -1

好玩的例子,干得漂亮!

尝试更改线程优先级,看看发生了什么,观察不同的计数(见下面的代码)。

也许考虑添加一个信号量,在两个线程之间传递计数,使它们平等执行,并报告3999999和4000000作为最终计数。

我相信你还有其他想法,感谢分享。

gcc main.c -o main
./main
初始计数器值:0
我是线程2。我计数了2000000次。全局计数器 = 3880728
我是线程1。我计数了2000000次。全局计数器 = 4000000
最终计数器:4000000
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

#define MAX 2000000UL
pthread_mutex_t lock;

struct shared_data
{
    int value;     /* 用于存储结果的共享变量 */
};

struct shared_data  *counter;

void* thread1Func(void * tid){
    uint32_t i = 0;
    while(i < MAX){
        if(pthread_mutex_trylock(&lock) == 0){
            counter->value++;
            pthread_mutex_unlock(&lock);
            i++;
        }
    }
    printf("我是线程1。我计数了%d次。全局计数器 = %d\n", i, counter->value);
    return NULL;
}

void* thread2Func(void * tid){
    uint32_t i = 0;
    while(i < MAX){
        if(pthread_mutex_trylock(&lock) == 0){
            counter->value++;
            pthread_mutex_unlock(&lock);
            i++;
        }
    }
    printf("我是线程2。我计数了%d次。全局计数器 = %d\n", i, counter->value);
    return NULL;
}

int main() {
    counter = (struct shared_data *) malloc(sizeof(struct shared_data));
    printf("初始计数器值:%d\n", counter->value);
    pthread_t thread1;
    pthread_t thread2;
    pthread_mutex_init(&lock, NULL);
    pthread_attr_t attr;
    struct sched_param sch_params;
    pthread_attr_init(&attr);
    pthread_attr_getschedparam(&attr, &sch_params);
    sch_params.sched_priority = 99;
    pthread_attr_setschedparam(&attr, &sch_params);
    pthread_create(&thread1, &attr, thread1Func, NULL);
    sch_params.sched_priority = 1;
    pthread_create(&thread2, &attr, thread2Func, NULL);
    pthread_join(thread1,NULL);
    pthread_join(thread2,NULL);
    printf("最终计数器:%d\n", counter->value);
    return 0;
}
英文:

Fun example, good work!

Try changing the thread priorities and see what happens to see different counts (see code below).

Maybe consider adding a semaphore to ping pong the count between the 2 threads so they execute equally and report 3999999 and 4000000 as the final counts.

I am sure you have other ideas too, thanks for posting.

gcc main.c -o main
./main
Initial Counter Value: 0
I am thread 2. I counted 2000000 times. Global counter = 3880728
I am thread 1. I counted 2000000 times. Global counter = 4000000
Final Counter: 4000000
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;unistd.h&gt;
#include &lt;pthread.h&gt;


#define MAX 2000000UL
pthread_mutex_t lock;
//pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

struct shared_data
{
    int value;     /* shared variable to store result*/
    
};

struct shared_data  *counter;


void* thread1Func(void * tid){
    uint32_t i = 0;
    while(i &lt; MAX){
        
        if(pthread_mutex_trylock(&amp;lock) == 0){
            counter-&gt;value++;
            pthread_mutex_unlock(&amp;lock);
            i++;
        }
    }
    printf(&quot;I am thread 1. I counted %d times. Global counter = %d\n&quot;, i, counter-&gt;value);
    return NULL;
}

void* thread2Func(void * tid){
    
    uint32_t i = 0;
    while(i &lt; MAX){
        
        if(pthread_mutex_trylock(&amp;lock) == 0){
            counter-&gt;value++;
            pthread_mutex_unlock(&amp;lock);
            i++;
        }

    }
    printf(&quot;I am thread 2. I counted %d times. Global counter = %d\n&quot;, i, counter-&gt;value);
    return NULL;
}


int main() {
    
    counter = (struct shared_data *) malloc(sizeof(struct shared_data));
    printf(&quot;Initial Counter Value: %d\n&quot;, counter-&gt;value);
    
    pthread_t thread1;
    pthread_t thread2;
    pthread_mutex_init(&amp;lock, NULL);

    pthread_attr_t attr;
    struct sched_param sch_params;
    pthread_attr_init(&amp;attr);
    pthread_attr_getschedparam(&amp;attr, &amp;sch_params);
    sch_params.sched_priority = 99;
    //pthread_attr_setschedpolicy(&amp;attr, SCHED_RR);
    pthread_attr_setschedparam(&amp;attr, &amp;sch_params);
    pthread_create(&amp;thread1, &amp;attr, thread1Func, NULL);

    sch_params.sched_priority = 1;
    pthread_create(&amp;thread2, &amp;attr, thread2Func, NULL);
    
    
    pthread_join(thread1,NULL);
    pthread_join(thread2,NULL);
    
    
    printf(&quot;Final Counter: %d\n&quot;, counter-&gt;value);
    return 0;
}

huangapple
  • 本文由 发表于 2023年2月18日 07:17:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/75490041.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定