并发程序实例

所有实例程序都由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;
属于并发引起的共享数据竞争的问题。

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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容

  • 必备的理论基础 1.操作系统作用: 隐藏丑陋复杂的硬件接口,提供良好的抽象接口。 管理调度进程,并将多个进程对硬件...
    drfung阅读 3,535评论 0 5
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,094评论 1 32
  • 一. 操作系统概念 操作系统位于底层硬件与应用软件之间的一层.工作方式: 向下管理硬件,向上提供接口.操作系统进行...
    月亮是我踢弯得阅读 5,965评论 3 28
  • 写在前面的话 代码中的# > 表示的是输出结果 输入 使用input()函数 用法 注意input函数输出的均是字...
    FlyingLittlePG阅读 2,753评论 0 8
  • 一、Python简介和环境搭建以及pip的安装 4课时实验课主要内容 【Python简介】: Python 是一个...
    _小老虎_阅读 5,738评论 0 10