linux17 线程安全 线程同步

1、线程安全:

多线程程序无论调度顺序如何,都能保证程序 的正确性,就说该程序处于线程安全的状态

1)、同步

2)、线程安全函数//有的函数不适合多线程使用,是函数自身的原因。

2、线程安全函数

1)非线程安全函数

分割函数//不是线程安全函数

strtok(buff,"  分隔符")//非线程安全函数,

如果有静态变量或者全局变量,对于多线程来说,访问是不安全的。属于非线程安全函数

#include
#include
#include
#include
#include

void *fun(void*arg)
{
char buff[128]={a b c d };
char*s=strtok(buff," ");
while(s!=NULL)
{
printf("%s\n",s);
s=strtok(NULL," ");
}

}

int main()
{
pthread_t id;
pthread_create(&id,NULL,fun,NULL);
char arr[128]={1 2 3 4 5};
char*p=strtok(arr," ");
whlie(p!=NULL)
{
printf("%s\n",p);
p=strtok(NULL," ");
}
pthread_join(id,NULL);
exit(0);
}

2)线程安全函数 

线程安全分割函数

strtok_r(buff," ",&ptr);

#include
#include
#include
#include
#include

void *fun(void*arg)
{
char buff[128]={a b c d };
char*ptr=NULL;
char*s=strtok_r(buff," ",&ptr);
while(s!=NULL)
{
printf("%s\n",s);
s=strtok_r(NULL," ",&ptr);
}

}

int main()
{
pthread_t id;
pthread_create(&id,NULL,fun,NULL);
char arr[128]={1 2 3 4 5};
char*ptr=NULL;
char*p=strtok_r(arr," ",&ptr);
whlie(p!=NULL)
{
printf("%s\n",p);
p=strtok_r(NULL," ",&ptr);
}
pthread_join(id,NULL);
exit(0);
}

3、多线程程序执行fork()

1)多线程程序:

#include
#include
#include
#include
#include

void*fun(void *arg)
{
for(int i=0;i<5;i++)
{
printf("fun(%d) run\n",getpid());
sleep(1);
}

}

int main()
{

pthread_t id;
pthread_create(&id,NULL,fun,NULL);


for(int i=0;i<5;i++)
{
printf("main(%d) run\n",getpid());
sleep(1);
}

pthread_join(id,NULL);
exit(0);
}

linux17 线程安全 线程同步_第1张图片

2)多线程 复制子进程

#include
#include
#include
#include
#include

void*fun(void *arg)
{
for(int i=0;i<5;i++)
{
printf("fun(%d) run\n",getpid());
sleep(1);
}

}

int main()
{

pthread_t id;
pthread_create(&id,NULL,fun,NULL);

fork ();

for(int i=0;i<5;i++)
{
printf("main(%d) run\n",getpid());
sleep(1);
}

pthread_join(id,NULL);
exit(0);
}

linux17 线程安全 线程同步_第2张图片

多线程 fork()后只会执行一条路径,他在哪一个路径中他就会执行那一条路径,但是其他路径的资源他是有的,只不过不执行了

4、创建一个锁,fork()之后看子进程的情况

#include
#include
#include
#include
#include
#include

pthread_mutex_t mutex;
void*fun(void *arg)
{

pthread_mutex_lock(&mutex);
sleep(5);//线程睡眠5秒
pthread_mutex_unlock(&mutex);
printf(" fun free\n");
}

int main()
{

pthread_t id;
pthread_mutex_init(&mutex,NULL);
pthread_create(&id,NULL,fun,NULL);

sleep(1);//主线程睡眠一秒

pid_t pid=fork();//复制的时候,父进程处于加锁状态
if(pid==0)
{
printf("child lock\n");
pthread_mutex_lock(&mutex);
printf("child success");
pthread_mutex_unlock(&mutex);
}
else
{
wait(NULL);
}

printf("main over");

pthread_mutex_destroy(&mutex);
pthread_join(id,NULL);
exit(0);

}

子进程没有加锁成功 

1)加锁失败原因:

 父进程和子进程的锁各自是各自的,是两把锁。

锁的状态,会在复制进程时,被复制,在复制时,父进程的锁是加锁,复制后,子进程的锁也是加锁,同样不加锁也是。是不固定的,子进程中锁的状态不清晰。

2)解决办法:pthread_atfork()

会在没有人用锁的情况下对进程进行复制,确保子进程所得状态时清晰的。

void parent_fun(void)
{
pthread_mutex_lock(&mutex);
}
void child_fun(void)
{
pthread_mutex_unlock(&mutex);
}


int main()
{
pthread_atfork(parent_fun,child_fun.child_fun);
//写入主函数,会在复制子程序之前执行
}

弊端是会延迟fork的复制

5、进程同步——条件变量

进程同步的方法:信号量  互斥锁   读写锁   条件变量

线程先将自己堵塞在条件变量等待队列上,等条件满足之后,唤醒一个或者全部

//条件满足就工作,条件不满足就休息//条件由用户决定。

在唤醒的时候,不希望有别的进出这个给队列,所以在唤醒时加锁

#include
#include
#include
#include
#include

pthread_mutex_t mutex;
pthread_cond_t cond;

char buff[128]={0};

void *funa(void*arg)
{
while(1)
{
    pthread_mutex_lock(&mutex);//唤醒前加锁
    pthread_cond_wait(&cond,&mutex);
    pthread_mutex_unlock(&mutex);

    if(strncmp(buff,"end",3)==0)
    {
        printf("funa:%s",buff);


    }




}

}
void*funb(void*arg)
{
{
    while (1)
    {
    pthread_mutex_lock(&mutex);
    pthread_cond_wait(&cond,&mutex);
    pthread_mutex_unlock(&mutex);
    }
        if(strncmp(buff,"end",3)==0)
    {
        printf("funb:%s",buff);


    }
    
}
}



int main()
{

pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cond,NULL);
pthread_t id1,id2;
pthread_create(&id1,NULL,funa,NULL);
pthread_create(&id2,NULL,funb,NULL);

while(1)
{
    char tmp[128]={0};
    fgets(tmp,128,stdin);

    strcpy(buff,tmp);
    if(strncmp(tmp,"end",3)==0)
    {

        pthread_cond_broadcast(&cond);//唤醒全部进程
        break;
    }
    else
    {
        pthread_cond_signal(&cond);//唤醒单个进程(轮流唤醒)

    }
}

pthread_join(id1,NULL);
pthread_join(id2,NULL);
}

你可能感兴趣的:(linux,服务器,算法)