linux 多线程问题——GDB调试_等问题

一、多线程,属于同一个进程

只有局部访问全局,没有全局访问局部,进程中的全局变量可以被同一进程中的多线程访问,

1、了解多线程:

解决多任务实现;

历史上Unix服务器不支持多线程,通过多进程(select模型来解决!)。

在Unix、linux实现多线程两种方式:

@1、内核支持多线程,内核重启来支持多线程

@2、使用进程的编程技巧封装进程,从而实现多线程,轻量级多线程,基于函数封装实现(API实现):libpthead.so(线程库);

多线程库:

libpthread.so   -lpthread(编译多线程时需加上);头文件:#include<pthread.h> 

编译方法:gcc -g pthread1.c -o pthread -lpthread

2、创建多线程

线程代码:回调函数实现,

线程ID:ID由进程管理,pthread_t 

创建、运行线程:pthread_create

       int pthread_create(pthread_t *thread, //线程id

const pthread_attr_t *attr,//线程属性
                           void *(*start_routine) (void *),//线程代码

 void *arg);//传递线程代码的数据

主进程结束后,里面的线程全结束!

进程问题,主进程结束,子进程不一定结束,但是,主进程里面的线程全结束。

pthread_join(pthread_t  pid,//线程ID

void **retval   //线程返回值);///等待子线程结束

创建子线程后,主线程继续完成系统分配

子线程结束就是线程函数饭后。

子线程与主线程有同等的的优先级,默认情况是同等的优先级。

例子1:

#include <pthread.h>
#include <stdio.h>
void *run(void *data)
{
        while(1)
        {
                printf("pthread!\n");
                sleep(1);
                sched_yield();
        }
}
int main()
{


        pthread_t pid;
        pthread_create(&pid,0,run,0);
        while(1)
        {
                sleep(1);
                printf("main pthread\n");
                sched_yield();
        }
        pthread_join(pid,(void**)0);
        sleep(2);
        return 0;
}

例子2.主线程+2个子线程

#include <pthread.h>
#include <stdio.h>
void *run(void *data)
{
        while(1)
        {
                printf("pthread1 !\n");
                sleep(1);
                sched_yield();
        }
}
void *run2(void *data)
{
        while(1)
        {
                printf("pthread2  !\n");
                sleep(1);
                sched_yield();
        }
}
int main()
{
        pthread_t pid,pid2;
        pthread_create(&pid,0,run,0);
        pthread_create(&pid2,0,run2,0);
        while(1)
        {
                sleep(1);
                printf("main pthread\n");
                sched_yield();
        }
        pthread_join(pid,(void**)0);
        pthread_join(pid2,(void**)0);
//      sleep(2);
        return 0;
}

/

gbd 调试:

run, br x(加断点),whatis a(a是什么类型),等等

/

3、线程的基本控制

线程的状体:ready->runny->deady

sleep()/pause()

3.1 结束线程的方法:第一种:可以在子线程的方式中void *run2(void *data),加上 return 返回值。

第二种: void pthread_exit(void *retval);

方法:

void *run(void *data)
{
        while(1)
        {
                printf("pthread1 !\n");
                sleep(1);
                sched_yield();
//              return "hang";//第一种
                pthread_exit("dian");//第二种
        }
}

3.2 线程的开始:

void *run(void *data)
{
        while(1)
        {
                printf("pthread1 ,%s!\n",data);
                sleep(1);
                sched_yield();
//              return "hang";
                pthread_exit("dian");
        }
}

int main()
{
        pthread_t pid,pid2;
        pthread_create(&pid,0,run,“data”);//"data"数据就可以传递到子线程的run方法中,
        pthread_create(&pid2,0,run2,0);
        while(1)
        {
                sleep(1);
                printf("main pthread\n");
                sched_yield();
        }
        pthread_join(pid,(void**)0);
        pthread_join(pid2,(void**)0);
//      sleep(2);
        return 0;
}

4、多线程问题:共享数据容易发生问题,多线程抢数据,

5、多线程问题的解决:

5.1互斥锁/互斥量 mutex

定义互斥量:pthread_mutex_t

初始化互斥量:pthread_mutex_init

互斥量操作:置0:pthread_mutex_lock;

判断互斥量0:阻塞,3:置0后再返回!

置1:pthread_mutex_unlock;;置1后返回!

释放互斥量:pthread_mutex_destroy

例子:互斥量的方法:

#include <pthread.h>

#include <stdio.h>
//定义互斥
pthread_mutex_t m ;
int a = 0, b = 0;
void destroy()
{

//加锁
        pthread_mutex_lock(&m);
        a++;
        b++;
//      pthread_mutex_unlock(&m);//在这个地方释放的锁的话,有输出
        if(a!=b)
        {
                printf("%d!=%d \n",a,b);
                a = b =0;
        }

//开锁
        pthread_mutex_unlock(&m);//锁在这个地方释放的话,没有输出
}
void *r1(void *data)
{
        while(1)
        {
                destroy();
        }
}
void *r2(void *data)
{
        while(1)
        {
                destroy();
        }
}
int main()
{
        pthread_t pid1,pid2;
        //初始化
        pthread_mutex_init(&m,0);
        pthread_create(&pid1,0,r1,0);
        pthread_create(&pid2,0,r2,0);
        pthread_join(pid1,(void**)0);
        pthread_join(pid2,(void**)0);

return 0;

}

/

总结:

mute锁之间的变量,指的是:同一个时间片内,只允许一个线程访问!,不代表值不变。

在lock和unlock之间,调用pthread_exit, pthread_cancel  其他线程将永久死锁!

/克服上面一些问题方法:

pthread_cleanup_push

pthread_cleanup_pop这对函数作用类似于atexit(进程使用),但是这两个函数并不是函数,而是宏!这两个必须成对使用!!!!

void pthread_cleanup_push(void (*routine)(void *), void *arg);
void pthread_cleanup_pop(int execute);

例子:

#include <stdio.h>
#include <pthread.h>
pthread_mutex_t  m;
void handle(void *d)
{
        printf("tuichu!");
}
void *runeven(void *d)
{
        int i = 0;
        for(i = 0;;i+=2)
        {
                pthread_mutex_lock(&m);
                pthread_cleanup_push(handle,0);
                printf("even:%d\n",i);
                sleep(1);
                pthread_cleanup_pop(0);
                pthread_mutex_unlock(&m);
        }
}
void *runodd(void *d)
{
        int i = 0;
        for(i = 1;;i+=2)
 {
                pthread_mutex_lock(&m);
                pthread_cleanup_push(handle,0);
                printf("odd:%d\n",i);
                pthread_cleanup_pop(0);
                pthread_mutex_unlock(&m);
        }
}
int main()
{
        pthread_t p1,p2;
        pthread_mutex_init(&m,0);
        pthread_create(&p1,0,runodd,0);
        pthread_create(&p2,0,runeven,0);
        sleep(3);
        pthread_cancel(p2);
        pthread_join(p1,(void*)0);
        pthread_join(p2,(void*)0);
        pthread_mutex_destroy(&m);
        return 0;
}
///

pthread_cleanup_pop和pthread_cleanup_push要在pthread_mutex_lock内

//

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值