C语言用泰勒公式啊并发~负载均衡

并发程序实例

2019-05-24  本文已影响0人  抚仙湖的小王子

所有实例程序都由C语言编写

实测,可运行

实例一

#include <stdio.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 i,ret;
  ret=pthread_create(&id,NULL,(void *) thread,NULL); // 成功返回0,错误返回错误编号
  if(ret!=0)
    {
    printf ("Create pthread error!\n");
    exit (1);
  }
  for(i=0;i<3;i++)
    {
    printf("This is the main process.\n");
    }
  pthread_join(id,NULL);
  return (0);
}

实例一分析:函数pthread_create用来创建一个线程,第一个参数为指向线程标识符的指针,第二个参数用来设置线程属性,第三个参数是线程运行函数的起始地址,最后一个参数是运行函数的参数,函数pthread_join用来等待一个线程的结束,第一个参数为被等待的线程标识符,第二个参数为一个用户定义的指针,它可以用来存储被等待线程的返回值。其中由于线程并发运行顺序的不确定性,会引起输出结果的随机性,这是由于线程争夺CPU资源造成的。属于并发引起的race condition.可以作为并发实例。

实例二:

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

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

/*给i的值和count的值加1*/
void *modify_i_thread(void *data)
{
 for(;;) 
     {
         i++;
         count++;
     }
 }
 
 /*给j的值和count的值加1*/
 void *modify_j_thread(void *data)
 {
     for(;;) {
         j++;
         count++;
     }
 }
 
 /*给k的值和count的值加1*/
 void *modify_k_thread(void *data)
 {
     for(;;) {
         k++;
         count++;
     }
 }
 
 int main(void)
 {
     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);
 
     /*打印结果    */    
     printf("i = %d, j = %d, k= %d, count = %d\n", i, j, k, count);
     printf("i+j+k=%d\n", i + j + k);
     
     return 0;
 }

实例二分析: 首先来看程序,程序很简单,就是创建了3个线程,第一个线程对i和count加1,第二个线程对j和count加1,第三个线程对k和count加1,i,j,k,count初始化都为0,这样的话,按照逻辑来说,最后i+j+k = count:仔细分析下创建的线程执行的操作,3个线程中都对count进行了++操作,++操作在C语言中看起来是一条语句,实际上编译后是3条语句,首先将count的值写入寄存器,然后对其进行加1操作,在接着将寄存器的值读出,保存在count中。

三个线程简称为A、B、C,如果A刚刚把count的值写入寄存器中,此时调度程序调度B线程开始运行,这个时候,B对count进行了N次加法操作,此时count = count+N,此时调度程序恢复执行A线程,那么此时A中保存的count的值却是是B线程执行前的值,此时,A再对count进行操作时,就是基于旧的值(其他线程对count进行操作前的值),而不是最新的值,所以count的值并不是我们期望中的值。
属于并发引起的数据竞争问题。(竞争count)

实例三:

#include <stdio.h>
#include <stdlib.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("奇数:%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("偶数:%d\n",i);
                usleep(100);
                pthread_mutex_unlock(&mutex);
        }
}
main()
{
        pthread_t todd,teven;         //定义两个线程
        pthread_mutex_init(&m,0);      //创建锁
        pthread_create(&todd,0,runodd,0);
        pthread_create(&teven,0,runeven,0);
        sleep(5);

        printf("外部强制停止todd线程\n");
        pthread_cancel(todd);

        pthread_join(todd,(void**)0);              //pthread_join()函数,以阻塞的方式等待thread指定的线程结束
        pthread_join(teven,(void**)0);
        pthread_mutex_destroy(&mutex);              //锁的释放
}

实例三分析: 属于并发引起的死锁问题,强制停止todd线程后,join函数还在以正常的状态等待,会导致teven线程一直死等。

实例四:

//假如我们要一直让thread1先执行减,thread2执行加,执行两个函数,顺序不确定的两个线程
#include <stdio.h>
#include <pthread.h>

int i=10;

void *func1(void *param)
{
    while(1)
    {
        if(i>0)
        {
            i--;
            printf("Thread 1::i    is  %d\n",i);
        }else
         {
            break;
        }
    }
    
}
void *func2(void *param)
{
    while(1)
    {
        if(i<10)
        {
            i++;
            printf("Thread 2::i   is  %d\n",i);
        }else
        {
            break;
        }
    }
    
}


int main()
{
    pthread_t threads[2];
    pthread_create(&threads[0],0,func1,0);
    pthread_create(&threads[1],0,func2,0);
    pthread_join(threads[0],0);
    pthread_join(threads[1],0);
    
    return 0;
}

实例四分析:两个函数,我们本想让函数一执行减法,函数二执行加法,串行下结果为10---1-----10,但是由于并行,会导致不可知数据,属于并发引起的数据竞争错误。

实例五:

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

int x;

int One()
{
    int y,z;
    x=1;
    y=0;
    if(x>=1)
    {
        y=y+1;
    }
    z=y;
    return (z);//第一个函数执行结果z=1
}
int Two()
{
    int y,z;
    x=0;
    y=0;
    if(x<1)
    {
        y=y+2;
    }
    z=y;
    return (z);//第二个函数执行结果z=2
}

void main()
{ 
    int pid;
    pid=fork();//,创建新进程成功后,系统中出现两个基本完全相同的进程,这两个进程执行没有固定的先后顺序,哪个进程先执行要看系统的进程调度策略。
    if ( pid == 0 ) //返回0证明创建子进程成功 
    {
        One();
    }
else {   
        Two(); 
     }
}

实例五分析:fork()函数作用:当程序调用fork()函数并返回成功之后,程序就将变成两个进程,调用fork()者为父进程,后来生成者为子进程。
若成功调用一次则返回两个值,子进程返回0,父进程返回子进程标记;否则,出错返回-1。
在复制时复制了父进程的堆栈段,所以两个进程都停留在fork函数中,等待返回,因此fork函数会返回两次,一次是在父进程中返回,另一次是在子进程中返回
1)在父进程中,fork返回新创建子进程的进程ID;
2)在子进程中,fork返回0;
属于并发引起的共享数据竞争的问题。

转载请注明出处,程序来自作者本科毕业设计案例

原创作者:抚仙湖的小王子

上一篇下一篇

猜你喜欢

热点阅读