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

前言:我在上大学时,对并发可能导致的问题进行了简单研究,其中下面的代码属于过程性结果,今日复盘拿出共享,希望您费劲找到的程序,能够发挥它的作用!
实例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!
注:配图来自网络。