欢迎光临散文网 会员登陆 & 注册

线程并发导致的经典“错误”案例——C语言

2023-03-14 16:01 作者:抚仙湖的小王子  | 我要投稿

前言:我在上大学时,对并发可能导致的问题进行了简单研究,其中下面的代码属于过程性结果,今日复盘拿出共享,希望您费劲找到的程序,能够发挥它的作用!

实例1:并发导致的线程争夺资源,线程争夺资源所导致的输出结果不唯一。

废话不多讲,上代码:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void thread(void){
    int i;
    for(i=0;i<3;i++){
         printf("This is a pthread.\n");
    }
}
int main(void){
     pthread_t id;
     int j;
     pthread_create(&id,NULL,(void *) thread,NULL);
     for(j=0;j<3;j++) {
          printf("This is the main process.\n");
      }
     pthread_join(id,NULL);
      return (0);
}

实例2:调用三个线程分别对三个变量进行增加,同时我们用count共享变量来监督增加的次数,但是由于线程并发的无序性,可能不能正确计算增加的次数

废话不多讲,上代码:

//this is a test
#include<stdio.h>
#include<stdlib.h>
#include <signal.h>
#include <unistd.h>
#include<pthread.h>

int count = 0;
int i=0;
int j=0;
int k=0;

void *modify_i_thread(void *data)
{
    for(i=0;i<100;i++)
   {
       i++;
       count++;
    }
}

void *modify_j_thread(void *data)
{
     for(j=0;j<100;j++)
    {
       j++;
       count++;
     }
}

void *modify_k_thread(void *data)
{
    for(k=0;k<100;k++)
   {
      k++;
      count++;
   }
}

int main(void)
{
   int a,b;
   pthread_t pthid;
 
   pthread_create(&pthid, NULL, modify_i_thread, NULL);
   pthread_create(&pthid, NULL, modify_j_thread, NULL);
   pthread_create(&pthid, NULL, modify_k_thread, NULL);

   sleep(1);

   for(a=0;a<i+j+k;a++)
       {
       b=(i+j+k)/count;
       count--;
       }

   return 0;
}

实例3:调用两个线程分别对奇数偶数进行计数,但是我们在强行关闭了其中一个线程,会导致死锁

废话不多讲,上代码:

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

pthread_mutex_t mutex;

void *runodd(void *d)
{
        int i=0;

        for(i=1;;i+=2)
        {
             pthread_mutex_lock(&mutex);
             printf("odd:%d\n",i);
             usleep(100);
             pthread_mutex_unlock(&mutex);
        }
}
void *runeven(void *d)
{
        int i=0;
        for(i=0;;i+=2)
        {
             pthread_mutex_lock(&mutex);
             printf("even:%d\n",i);
             usleep(100);
             pthread_mutex_unlock(&mutex);
        }
}

int main()
{
        pthread_t todd,teven;
        pthread_mutex_init(&mutex,0);
        pthread_create(&todd,0,runodd,0);
        pthread_create(&teven,0,runeven,0);

        sleep(5);

        printf("stop todd process\n");

        pthread_cancel(todd);
        pthread_join(todd,(void**)0);
        pthread_join(teven,(void**)0);
        pthread_mutex_destroy(&mutex);
}

实例5:执行结果取决于主线程main函数何时终止,线程thread1、thread2是否能够来得急执行它们的函数争夺执行权。
属于race condition 问题。

废话不多讲,上代码:

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

int g_Flag=0;

void* thread1(void*);
void* thread2(void*);

int main(int argc, char** argv)
{
    printf("enter main\n");
    pthread_t tid1, tid2;
    int rc1=0, rc2=0;
    rc2 = pthread_create(&tid2, NULL, thread2, NULL);
    if(rc2 != 0)
        printf("%s: %d\n",__func__, strerror(rc2));

    rc1 = pthread_create(&tid1, NULL, thread1, &tid2);
    if(rc1 != 0)
        printf("%s: %d\n",__func__, strerror(rc1));
    printf("leave main\n");
    exit(0);    
}

void* thread1(void* arg)
{
    printf("enter thread1\n");
    printf("this is thread1, g_Flag: %d, thread id is %u\n",g_Flag, (unsigned int)pthread_self());
    g_Flag = 1;
    printf("this is thread1, g_Flag: %d, thread id is %u\n",g_Flag, (unsigned int)pthread_self());
    printf("leave thread1\n");
    pthread_exit(0);
}


void* thread2(void* arg)
{
    printf("enter thread2\n");
    printf("this is thread2, g_Flag: %d, thread id is %u\n",g_Flag, (unsigned int)pthread_self());
    g_Flag = 2;
    printf("this is thread1, g_Flag: %d, thread id is %u\n",g_Flag, (unsigned int)pthread_self());
    printf("leave thread2\n");
    pthread_exit(0);
}

以上代码均可运行,基本覆盖并发可能导致的各种情况,如果要对这些错误进行检测,需要用到Spin工具,读到这里还不走,那么接下来您可能会用到Linux或者Cygwin,安装Spin( Spin(Simple Promela Interpreter)是一个流行的开源软件验证工具)进行检测验证。

希望能够帮到有缘人吧!

留个赞再走呗!thanks!

注:配图来自网络。

线程并发导致的经典“错误”案例——C语言的评论 (共 条)

分享到微博请遵守国家法律