美文网首页
Linux多线程编程

Linux多线程编程

作者: 雪上霜 | 来源:发表于2020-04-13 10:25 被阅读0次

Linux多线程编程

  • 使用线程的目的就是要合理的利用资源,提高cpu的效率。

  • 进程:一个正在运行的程序,资源分配的最小单位。

  • 线程:cpu调度的基本单位。

360截图20200410171847590.jpg 360截图20200410171935235.jpg 360截图20200410172010428.jpg
  • 并发:同一个时间段内,不同的事情交替的进行操作。(单核的,假象)

  • 并行:同一个时刻内,不同的事情做多个事情进行操作。(多核的)

  • 同步:彼此有依赖关系的调用不应该同事发生,同步就是要阻止那些"同时发生"的事情。

  • 异步:任何两个彼此独立的操作是异步的,它表明事情的独立发生。

360截图20200410172822829.jpg

include<pthread.h>

编译时要用到pthread 库:gcc -lpthread

//pthreadid.c
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
​
int main()
{
 //pid_t 和pthread_t 都是unsigned long int 类型,
 //其他的FreeBSD,MacOS 中pthread_t不是此类型。
 pid_t pid; 
 pthread_t tid;
 pid = getpid();
 tid = pthread_self();

 printf("pid is %u,tid is %lu",pid,tid);

 return 0;
}
360截图20200410173416453.jpg

错误码位置:/usr/include/asm-generic/errno.h

360截图20200410173956523.jpg
//pthread_create.c
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
​
​
void print_id(char *s)
{
 pid_t pid;
 pthread_t tid;

 pid = getpid();
 tid = pthread_self();

 printf("%s pid is %u,tid is 0x%lx\n",s,pid,tid);
}
​
void *thread_fun(void *arg)
{
 print_id(arg);
 return (void*)0;
}
​
int main()
{
 pthread_t ntid;
 int err;

 err = pthread_create(&ntid,NULL,thread_fun,"new thread");
 if(err != 0)
 {
 printf("create new thread failed\n");
 return 0;
 }

 print_id("main thread:");
 sleep(2);
​
 return 0;
}

gcc pthread_create.c -lpthread

  • 主线程利用pthread_exit退出,其他线程不会退出。

  • 如果return main函数返回,则其他线程也就退出了。

360截图20200410180504334.jpg
//main_thread.c
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
​
struct student{
 int age;
 char name[20];
 char id[4];
};
​
void *thread_fun(void *stu)
{
 printf("student age is %d,name is %s,id is %s\n",((struct student*)stu)->age,((struct student*)stu)->name,((struct student*)stu)->id);
}
​
int main(int argc,char* argv[])
{
 pthread_t ntid;
 int err;
 int *rval;

 struct student stu;
 stu.age = 20;
 memcpy(stu.name,"zhangsan",20);
 memcpy(stu.id,"0083",5);

 err = pthread_create(&ntid,NULL,thread_fun,(void*)(&stu));
 if(err != 0)
 {
 printf("create new thread failed\n");
 return 0;
 }
​
 int i;
 printf("main thread have %d args\n",argc);
 for(i = 0;i < argc;i++)
 {
 printf("main thread argv is %s\n",argv[i]);
 }
 //sleep(1);

 pthread_exit(rval);

 return 0;
}

思考:主子线程交替打印奇数偶数。

  • 线程的几种状态:就绪,运行,阻塞,终止


    image.png
  • 如果进程中的任意一个线程调用了exit,_Exit, _exit,那么整个进程就终止。

  • 不终止进程的线程终止方式:

    • 从启动例程中返回,返回值是线程的退出码

    • 线程可以被同一个进程中的其他线程取消

    • 线程调用pthread_exit(void *rval)函数,rval是退出码

  • 360截图20200410184643250.jpg
//thread_exit.c
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
​
//验证调用exit ,return ,pthread_exit 函数是否会引起主进程的退出。
void *thread_fun(void *arg)
{
 if(strcmp("1",(char*)arg) == 0)
 {
 printf("new thread return !\n");
 return (void*)1;
 }
 if(strcmp("2",(char*)arg) == 0)
 {
 printf("new thread pthread_exit !\n");
 pthread_exit((void*)2);
 }
 if(strcmp("3",(char*)arg) == 0)
 {
 printf("new thread exit !\n");
 exit(3);
 }
}
​
int main(int argc,char *argv[])
{
​
 pthread_t tid;
 int err;
 err = pthread_create(&tid,NULL,thread_fun,(void*)argv[1]);
 if(err != 0)
 {
 printf("creae new thread failed\n");
 return 0;
 }

 sleep(1);
 printf("main thread\n");
​
 return 0;
}
  • 思考:创建多个线程,证明任意一个线程调用exit函数都会导致进程的退出。
360截图20200410195853521.jpg
360截图20200410200000300.jpg
//thread_join.c
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
​
void *thread_fun(void* arg)
{
 printf("wo shi thread1 \n");
 return (void*)1;
}
​
void* thread_fun2(void* arg)
{
 printf("wo shi thread2 \n");
 pthread_detach(pthread_self());
 pthread_exit((void*)2);
}
​
int main()
{
 int err1,err2;
 pthread_t tid1,tid2;
 void *rval1,*rval2;

 err1 = pthread_create(&tid1,NULL,thread_fun,NULL);
 err2 = pthread_create(&tid2,NULL,thread_fun2,NULL);

 if(err1 || err2)
 {
 printf("create new thread failed\n");
 return 0;
 }

 printf("main thread\n");

 printf("join1 rval is %d\n",pthread_join(tid1,&rval1));
 printf("join2 rval is %d\n",pthread_join(tid2,&rval2));

 printf("thread 1 exit code is %d\n",(int*)rval1);
 printf("thread 2 exit code is %d\n",(int*)rval2);

 printf("wo shi main thread\n");

 return 0; 
}
  • 思考:证明当pthread_join()返回以后,其他线程不能调用pthread_join连接id指定的线程
360截图20200410202618650.jpg
360截图20200410202635779.jpg
360截图20200410202715267.jpg
360截图20200410202825659.jpg
360截图20200410202905481.jpg
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
​
void *thread_fun(void* arg)
{
 int stateval;
 stateval = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
 if(stateval != 0)
 {
 printf("set cancel state failed\n");
 }

 printf("Im new thread\n");
 sleep(4);

 printf("about to cancel\n");
 stateval = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
 //stateval = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
 if(stateval != 0)
 {
 printf("set cancel state failed\n");
 }
 int typeval = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
 if(typeval != 0)
 {
 printf("set cancel type failed\n");
 }
 printf("first cancel point\n");
 printf("second cancel point\n");

 return (void*)20;
}
​
​
​
int main()
{
​
 pthread_t tid;
 int err,cval,jval;
 void *rval;

 err = pthread_create(&tid,NULL,thread_fun,NULL);
 if(err != 0)
 {
 printf("create thread failed\n");
 return 0;
 }
 sleep(2);

 cval = pthread_cancel(tid);
 if(cval != 0)
 {
 printf("cancel thread failed\n");
 }
 jval = pthread_join(tid,&rval);

 printf("new thread exit code is %d\n",(int*)rval);

 return 0;
}
![ 360截图20200410202618650.jpg

思考:证明线程可以自己取消自己。

360截图20200410205105491.jpg
//
#include<stdio.h>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>

void *thread_fun(void *arg)
{
    sleep(1);
    printf("wo shi new thread\n");
    return (void*)0;
}

int main()
{
    pthread_t tid;
    int err;
    int s;
    void *rval;
    
    err = pthread_create(&tid,NULL,thread_fun,NULL);    
    if(err != 0)
    {
        printf("cancel new thread failed\n");
        return 0;
    }
    sleep(1);
    
    s = pthread_kill(tid,0);
    //s = pthread_kill(tid,SIGQUIT);
    if(s == ESRCH)
    {
        printf("thread tid is not found\n");
    }
    pthread_join(tid,&rval);
    printf("wo shi main thread\n");
    
    return 0;
}
360截图20200411081047852.jpg 360截图20200411081313301.jpg
360截图20200411081335207.jpg
360截图20200411081350134.jpg
//thread.kill.c
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>

void sig_handler1(int arg)
{
    printf("thread1 get signal\n");
    return;
}
void sig_handler2(int arg)
{
    printf("thread2 get signal\n");
    return;
}

void *thread_func(void* arg)
{
    printf("new thread 1\n");
    struct sigaction act;
    memset(&act,0,sizeof(act));
    act.sa_handler = sig_handler1;
    sigaction(SIGQUIT,&act,NULL);
    
    pthread_sigmask(SIG_BLOCK,&act.sa_mask,NULL);
    sleep(2);
}

void *thread_func2(void* arg)
{
    printf("new thread 2\n");
    struct sigaction act;
    memset(&act,0,sizeof(act));
    act.sa_handler = sig_handler2;
    sigaction(SIGQUIT,&act,NULL);
    
    //pthread_sigmask(SIG_BLOCK,&act.sa_mask,NULL);
    sleep(2);
}

int main()
{
    pthread_t tid1,tid2;
    int err;
    int s;
    
    err = pthread_create(&tid1,NULL,thread_fun,NULL);
    if(err != 0)
    {
        printf("create new thread 1 failed\n");
        return ;
    }
    
    err = pthread_create(&tid2,NULL,thread_fun2,NULL);
    if(err != 0)
    {
        printf("create new thread 2 failed\n");
        return ;
    }
    
    sleep(1);
    
    s = pthread_kill(tid1,SIGQUIT);
    if(s != 0)
    {
        printf("send signal to thread1 failed\n");
    }
    s = pthread_kill(tid2,SIGQUIT);
    if(s != 0)
    {
        printf("send signal to thread2 failed\n");
    }
    
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
    
    return 0;
}

思考:证明SIGKILL和SIGSTOP 是无法阻塞的。


360截图20200411082537583.jpg
360截图20200411082703520.jpg
//thread_clean.c
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>

void *first_clean(void* arg)
{
    printf("%s first clean\n",arg);
    return (void*)0;
}

void *second_clean(void* arg)
{
    printf("%s second clean\n",arg);
    return (void*)0;
}

void *thread_fun1(void *arg)
{
    printf("new thread1 \n");
    pthread_cleanup_push(first_clean,"thread1");
    pthread_cleanup_push(second_clean,"thread1");
    
    pthread_cleanup_pop(1);
    pthread_cleanup_pop(0);
    
    return (void*)1;
}

void *thread_fun2(void *arg)
{
    printf("new thread2 \n");
    pthread_cleanup_push(first_clean,"thread2");
    pthread_cleanup_push(second_clean,"thread2");
    
    pthread_cleanup_pop(0);
    pthread_cleanup_pop(0);
    
    pthread_exit((void*)2);
}

int main()
{
    pthread_t tid1,tid2;
    int err;
    
    err = pthread_create(&tid1,NULL,thread_fun1,NULL);
    if(err != 0)
    {
        printf("create new thread1 failed\n");
        return;
    }
    
    err = pthread_create(&tid1,NULL,thread_fun2,NULL);
    if(err != 0)
    {
        printf("create new thread2 failed\n");
        return;
    }
    sleep(2);
    
    return 0;
}
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>

struct student{
    int id;
    int age;
    int name;
}stu;

int i;

void *thread_fun1(void *arg)
{
    while(1)
    {
        stu.id = i;
        stu.age = i;
        stu.name = i;
        i++;
        if(stu.id != stu.age || stu.id != stu.name || stu.age != stu.name)
        {
            printf("%d,%d,%d\n",stu.id,stu.age,stu.name);
            break;
        }
    }
    
    return (void*)0;
}

void *thread_fun2(void *arg)
{
    while(1)
    {
        stu.id = i;
        stu.age = i;
        stu.name = i;
        i++;
        if(stu.id != stu.age || stu.id != stu.name || stu.age != stu.name)
        {
            printf("%d,%d,%d\n",stu.id,stu.age,stu.name);
            break;
        }
    }
    
    return (void*)0;
}

int main()
{
    pthread_t tid1,tid2;
    int err;
    
    err = pthread_create(&tid1,NULL,thread_fun1,NULL);
    if(err != 0)
    {
        printf("create new thread1 failed\n");
        return;
    }
    
    err = pthread_create(&tid2,NULL,thread_fun2,NULL);
    if(err != 0)
    {
        printf("create new thread 2failed\n");
        return;
    }
    
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
    
    return 0;
}
360截图20200411082736580.jpg
360截图20200411084557401.jpg

/usr/include/bits/pthreadtypes.h中查看pthread_mutex_t

360截图20200411085525294.jpg
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>

struct student{
    int id;
    int age;
    int name;
}stu;

int i;
pthread_mutex_t mutex;

void* thread_fun1(void *arg)
{
    while(1)
    {
        pthread_mutex_lock(&mutex);
        stu.id = i;
        stu.age = i;
        stu.name = i;
        i++;
        if(stu.id != stu.age || stu.id != stu.name || stu.age != stu.name)
        {
            printf("%d,%d,%d\n",stu.id,stu.age,stu.name);
            break;
        }
        pthread_mutex_unlock(&mutex);
    }
    
    return (void*)0;
}

void* thread_fun2(void *arg)
{
    while(1)
    {
        pthread_mutex_lock(&mutex);
        stu.id = i;
        stu.age = i;
        stu.name = i;
        i++;
        if(stu.id != stu.age || stu.id != stu.name || stu.age != stu.name)
        {
            printf("%d,%d,%d\n",stu.id,stu.age,stu.name);
            break;
        }
        pthread_mutex_unlock(&mutex);
    }
    
    return (void*)0;
}

int main()
{
    pthread_t tid1,tid2;
    int err;
    
    err = pthread_mutex_init(&mutex,NULL);
    if(err != 0)
    {
        printf("init mutext failed\n");
        return;
    }
    
    err = pthread_create(&tid1,NULL,thread_fun1,NULL);
    if(err != 0)
    {
        printf("create new thread1 failed\n");
        return;
    }
    
    err = pthread_create(&tid2,NULL,thread_fun2,NULL);
    if(err != 0)
    {
        printf("create new thread 2failed\n");
        return;
    }
    
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
    
    return 0;
}
360截图20200411090332958.jpg
360截图20200411090556086.jpg
360截图20200411090624470.jpg
360截图20200411091028102.jpg
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>


int num = 0;
pthread_rwlock_t rwlock;

void* thread_fun1(void *arg)
{
    int err;
    pthread_rwlock_rdlock(&rwlock);
    //pthread_rwlock_wrlock(&rwlock);
    printf("thread 1 print num %d\n",num);
    sleep(5);
    printf("thread 1 over\n");
    pthread_rwlock_unlock(&rwlock);
    
    return (void*)1;
}

void* thread_fun2(void *arg)
{
    int err;
    //pthread_rwlock_rdlock(&rwlock);
    pthread_rwlock_wrlock(&rwlock);
    printf("thread 2 print num %d\n",num);
    sleep(5);
    printf("thread 2 over\n");
    pthread_rwlock_unlock(&rwlock);
    
    return (void*)1;
}

int main()
{
    pthread_t tid1,tid2;
    int err;
    
    
    err = pthread_rwlock_init(&rwlock,NULL);
    if(err != 0)
    {
        printf("init rwlock failed\n");
        return;
    }
    
    err = pthread_create(&tid1,NULL,thread_fun1,NULL);
    if(err != 0)
    {
        printf("create new thread1 failed\n");
        return;
    }
    
    err = pthread_create(&tid2,NULL,thread_fun2,NULL);
    if(err != 0)
    {
        printf("create new thread 2failed\n");
        return;
    }
    
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
    
    pthread_rwlock_destroy(&rwlock);
    
    return 0;
}

思考:用多线程将一个文件1.c拷贝3个副本,11.c,12.c,13.c

360截图20200411093041428.jpg
360截图20200411093156939.jpg
360截图20200411093353477.jpg
360截图20200411093600392.jpg
360截图20200411093802043.jpg
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

#define BUFFER_SIZE 5   //产品库存大小
#define PRODUCT_CNT 30  //产品生成总数

struct product_cons
{
    int buffer[BUFFER_SIZE];    //生产产品值
    pthread_mutex_t lock;       //互斥锁 volatile int
    int readpos,writepos;       //读写位置
    pthread_cond_t notempty;    //条件变量非空
    pthread_cond_t notfull;     //非满
}buffer;

void init(struct product_cons *p)
{
    pthread_mutex_init(&p->lock,NULL);      //互斥锁
    pthread_cond_init(&p->notempty,NULL);   //条件变量
    pthread_cond_init(&p->notfull,NULL);    //条件变量
    p->readpos = 0;
    p->writepos = 0;
}

void finish(struct product_cons *p)
{
    pthread_mutex_destroy(&p->lock);    //互斥锁
    pthread_cond_destroy(&p->notempty); //条件变量
    pthread_cond_destroy(&p->notfull);  //条件变量
    p->readpos = 0;
    p->writepos = 0;
}

//存储一个数据到buffer
void put(struct product_cons *p,int data)   //输入产品子函数
{
    pthread_mutex_lock(&p->lock);
    if((p->writepos+1) % BUFFER_SIZE == p->readpos)
    {
        printf("producer wait for not full\n");
        pthread_cond_wait(&p->notfull,&p->lock);
    }
    p->buffer[p->writepos] = data;
    p->writepos++;
    if(p->writepos >= BUFFER_SIZE)
        p->writepos = 0;
        
    pthread_cond_signal(&p->notempty);
    pthread_mutex_unlock(&p->lock);
}

//读,移除一个数据从buffer
int get(struct product_cons *p)
{
    int data;
    
    pthread_mutex_lock(&p->lock);
    if(p->readpos == p->writepos)
    {
        printf("consumer wait for not empty\n");
        pthread_cond_wait(&p->notempty,&p->lock);
    }
    data = p->buffer[p->readpos];
    p->readpos++;
    if(p->readpos >= BUFFER_SIZE)
        p->readpos = 0;
    pthread_cond_signal(&p->notfull);
    
    pthread_mutex_unlock(&p->lock);
    return data;
}

void *producer(void* data)  //子线程,生产
{
    int n;
    for(n = 1;n <= 50;n++)  //生成50个产品
    {
        sleep(1);
        printf("put the %d product ...\n",n);
        put(&buffer,n);
        printf("put the %d product success\n",n);
    }
    printf("producer stopped\n");
    return NULL;
}

void *consumer(void* data)
{
    static int cnt = 0;
    int num;
    while(1)
    {
        sleep(2);
        printf("get product ...\n");
        num = get(&buffer);
        printf("get the %d product success\n",num);
        if(++cnt == PRODUCT_CNT)
            break;
    }
    printf("consumer stopped\n");
    return NULL;
}

int main(int argc,char* argv[])
{
    pthread_t th_a,th_b;
    void* retval;
    
    init(&buffer);
    
    pthread_create(&th_a,NULL,producer,0);
    pthread_create(&th_b,NULL,consumer,0);
    
    pthread_join(th_a,&retval);
    pthread_join(th_b,&retval);
    
    finish(&buffer);
    
    return 0;
}

思考:多个生产者和消费者

360截图20200411193914860.jpg
360截图20200411194257729.jpg
360截图20200411194317698.jpg
360截图20200411194514049.jpg
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

pthread_once_t once = PTHREAD_ONCE_INIT;
pthread_t tid;

void thread_init()
{
    printf("I'm in thread 0x%x\n",tid);
}

void *thread_fun1(void* arg)
{
    tid = pthread_self();
    printf("I'm thread 1 0x%x\n",tid);
    printf("once is %d\n",once);
    pthread_once(&once,thread_init);
    printf("once is %d\n",once);
    
    return NULL;
}

void *thread_fun2(void* arg)
{
    sleep(2);
    tid = pthread_self();
    printf("I'm thread 2 0x%x\n",tid);
    pthread_once(&once,thread_init);
    
    return NULL;
}

int main()
{
    pthread_t tid1,tid2;
    int err;
    
    err = pthread_create(&tid1,NULL,thread_fun1,NULL);
    if(err != 0)
    {
        printf("create new thread 1 failed\n");
        return;
    }
    
    err = pthread_create(&tid2,NULL,thread_fun2,NULL);
    if(err != 0)
    {
        printf("create new thread 2 failed\n");
        return;
    }
    
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
    
    return 0;   
}

思考:将互斥量等初始化使用pthread_once实现。

360截图20200411195500756.jpg
360截图20200411195610528.jpg 360截图20200411195636444.jpg
360截图20200411195652960.jpg
360截图20200411195805978.jpg
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>


void *thread_fun1(void* arg)
{
    printf("I'm thread 1 \n");
    
    return (void*)1;
}

void *thread_fun2(void* arg)
{
    printf("I'm thread 2\n");
    
    return (void*)2;
}

int main()
{
    pthread_t tid1,tid2;
    int err;
    
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
    //pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE);
    
    err = pthread_create(&tid1,&attr,thread_fun1,NULL);
    if(err != 0)
    {
        printf("create new thread 1 failed\n");
        return;
    }
    
    err = pthread_create(&tid2,NULL,thread_fun2,NULL);
    if(err != 0)
    {
        printf("create new thread 2 failed\n");
        return;
    }
    
    err = pthread_join(tid1,NULL);
    if(!err)
        printf("join thread 1 success\n");
    else
        printf("join thread 1 failed\n");
        
    
    err = pthread_join(tid2,NULL);
    if(!err)
        printf("join thread 2 success\n");
    else
        printf("join thread 2 failed\n");   
    
    pthread_attr_destroy(&attr);
    
    return 0;   
}

思考:设置线程的分离属性,然后在新县城中获取自己的分离属性。

360截图20200411200637349.jpg
360截图20200411200902258.jpg
360截图20200411201053386.jpg
360截图20200411201105539.jpg
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <limits.h>


pthread_attr_t attr;

void *thread_fun(void* arg)
{
    size_t stacksize;
#ifdef _POSIX_THREAD_ATTR_STACKSIZE
    pthread_attr_getstacksize(&attr, &stacksize);
    printf("new thread stack size is %d\n",stacksize);
    pthread_attr_setstacksize(&attr, 16389);
    pthread_attr_getstacksize(&attr, &stacksize);
    printf("new thread stack size is %d\n",stacksize);
#endif

    printf("new thread stack size is %d\n",stacksize);
    
    return(void*)1;
}

int main()
{
    pthread_t tid;
    int err;
    
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE);
    
#ifdef _POSIX_THREAD_ATTR_STACKSIZE
    pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN);
#endif

    err = pthread_create(&tid,&attr,thread_fun,NULL);
    if(err)
    {
        printf("create new thread failed\n");
        return;
    }
    
    pthread_join(&tid,NULL);
    //pthread_attr_destroy(&attr);
    
    return 0;
}
360截图20200413081209017.jpg
360截图20200413081310718.jpg
360截图20200413081440824.jpg
360截图20200413081748055.jpg
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>


int main()
{
    char *shm = "myshm";
    char *shm1 = "myshm1";
    int shm_id,shm1_id;
    char *buf;
    pid_t pid;
    
    pthread_mutex_t *mutex;
    pthread_mutexattr_t mutexattr;
    
    //打开共享内存
    shm1_id = shm_open(shm1,O_RDWR|O_CREAT,0644);
    //调整共享内存大小
    ftruncate(shm1_id,100);
    //映射共享内存,MAP_SHARED属性表明,对共享内存的任何修改都会影响其他进程
    mutex = (pthread_mutex_t*)mmap(NULL,100,PROT_READ|PROT_WRITE,MAP_SHARED,shm1_id,0);
    
    pthread_mutexattr_init(&mutexattr);
#ifdef _POSIX_THREAD_PROCESS_SHARED
    pthread_mutexattr_setpshared(&mutexattr,PTHREAD_PROCESS_SHARED);
#endif
    pthread_mutex_init(mutex,&mutexattr);
    
    //打开共享内存
    shm_id = shm_open(shm,O_RDWR|O_CREAT,0644);
    //调整共享内存大小
    ftruncate(shm_id,100);
    //映射共享内存,MAP_SHARED属性表明,对共享内存的任何修改都会影响其他进程
    buf = (char*)mmap(NULL,100,PROT_READ|PROT_WRITE,MAP_SHARED,shm_id,0);
    
    pid = fork();
    if(pid == 0)
    {
        //休眠1s,让父进程先运行
        sleep(1);
        printf("I'm child process\n");
        
        pthread_mutex_lock(mutex);
        //将共享内存内容修改为hello
        memcpy(buf,"hello",6);
        pthread_mutex_unlock(mutex);
        printf("child buf is :%s\n",buf);
    }
    else if(pid > 0)
    {
        printf("I'm parent process\n");
        
        pthread_mutex_lock(mutex);
        //修改共享内存内容为world
        memcpy(buf,"world",6);
        sleep(3);
        pthread_mutex_unlock(mutex);
        printf("parent buf is : %s\n",buf);
    }
    
    pthread_mutexattr_destroy(&mutexattr);
    pthread_mutex_destroy(mutex);
    
    //解除映射
    munmap(buf,100);
    //消除共享内存
    shm_unlink(shm);
    
    //解除映射
    munmap(mutex,100);
    //消除共享内存
    shm_unlink(shm1);
    
    return 0;
}
  • gcc -lrt :连接共享内存的库
360截图20200413083540166.jpg
360截图20200413083601975.jpg

思考:如果将互斥量的进程共享属性设为PTHREAD_PROCESS_PRIVATTE会是什么结果,为什么?


360截图20200413084019101.jpg
360截图20200413084715239.jpg
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

void *thread_fun1(void* arg)
{
    printf("thread 1 start!\n");
    open("1.c",O_RDWR);
    sleep(2);
    printf("thread 1 errno is :%d\n",errno);
}

void *thread_fun2(void *arg)
{
    sleep(1);
    printf("thread 2 start !\n");
    open("t.c","O_RDWR");
    printf("thread 2 errno is :%d\n",errno);
}

int main()
{
    ptread_t tid1,tid2;
    
    if(pthread_create(&tid1,NULL,thread_fun1,NULL));
    {
        printf("create new thread 1 failed\n");
        return;
    }
    if(pthread_create(&tid2,NULL,thread_fun2,NULL));
    {
        printf("create new thread 2 failed\n");
        return;
    }
    
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
    
    return;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

pthread_key_t key;

void *thread_fun1(void* arg)
{
    printf("thread 1 start!\n");
    int a = 1;
    pthread_setspecific(key,(void*)a);
    sleep(2);
    printf("thread 1 key -->data is %d\n",pthread_getspecific(key));
}

void *thread_fun2(void *arg)
{
    sleep(1);
    printf("thread 2 start !\n");
    int a = 2;
    pthread_setspecific(key,(void*)a);
    sleep(2);
    printf("thread 2 key -->data is %d\n",pthread_getspecific(key));
}

int main()
{
    pthread_t tid1,tid2;
    
    pthread_key_create(&key,NULL);
    
    if(pthread_create(&tid1,NULL,thread_fun1,NULL))
    {
        printf("create new thread 1 failed\n");
        return;
    }
    if(pthread_create(&tid2,NULL,thread_fun2,NULL))
    {
        printf("create new thread 2 failed\n");
        return;
    }
    
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
    
    pthread_key_delete(&key);
    
    return;
}

思考:将一块动态申请的内存关联到key,访问pthread_getspecific(key),请注意内存的销毁。

360截图20200413090630982.jpg
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALLIZER;

void *thread_fun(void *arg)
{
    sleep(1);
    pid_t pid;
    pid = fork();
    if(pid == 0)
    {
        pthread_mutex_lock(&mutex);
        printf("child\n");
        pthread_mutex_unlock(&mutex);
    }
    if(pid > 0)
    {
        pthread_mutex_lock(&mutex);
        printf("parent\n");
        pthread_mutex_unlock(&mutex);
    }
}

int main()
{
    pthread_t tid;
    
    if(pthread_create(&tid,NULL,thread_fun,NULL)
    {
        printf("create new thread failed\n");
        return;
    }
    
    pthread_mutex_lock(&mutex);
    sleep(2);
    pthread_mutex_unlock(&mutex);
    printf("main\n");
    pthread_join(tid,NULL);
    
    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALLIZER;

void *thread_fun(void *arg)
{
    sleep(1);
    printf("new thread\n");
    
    pid_t pid;
    pthread_mutex_lock(&mutex);
    
    pid = fork();
    if(pid == 0)
    {
        pthread_mutex_unlock(&mutex);
        printf("child\n");
    }
    if(pid > 0)
    {
        pthread_mutex_unlock(&mutex);
        printf("parent\n");
    }
}

int main()
{
    pthread_t tid;
    
    if(pthread_create(&tid,NULL,thread_fun,NULL)
    {
        printf("create new thread failed\n");
        return;
    }
    
    printf("main\n");
    pthread_join(tid,NULL);
    
    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALLIZER;

void prepare()
{
    pthread_mutex_lock(&mutex);
    printf("I'm prepare\n");
}

void parent()
{
    pthread_mutex_unlock(&mutex);
    printf("I'm parent\n");
}

void child()
{
    pthread_mutex_unlock(&mutex);
    printf("I'm child\n");
}

void *thread_fun(void *arg)
{
    sleep(1);
    pid_t pid;
    
    pthread_atfork(prepare,parent,child);
    
    pid = fork();
    if(pid == 0)
    {
        pthread_mutex_lock(&mutex);
        printf("child process\n");
        pthread_mutex_unlock(&mutex);
    }
    if(pid > 0)
    {
        pthread_mutex_lock(&mutex);
        printf("parent process\n");
        pthread_mutex_unlock(&mutex);
    }
}

int main()
{
    pthread_t tid;
    
    if(pthread_create(&tid,NULL,thread_fun,NULL)
    {
        printf("create new thread failed\n");
        return;
    }
    
    pthread_mutex_lock(&mutex);
    sleep(2);
    printf("main\n");
    pthread_mutex_unlock(&mutex);
    
    pthread_join(tid,NULL);
    
    pthread_mutex_destroy(&mutex);
    
    return 0;
}
360截图20200413092228289.jpg
360截图20200413092851137.jpg
360截图20200413093036581.jpg
360截图20200413093119391.jpg
360截图20200413093226285.jpg
360截图20200413093257429.jpg
360截图20200413093353172.jpg
360截图20200413093427388.jpg 360截图20200413093516998.jpg
360截图20200413093547124.jpg
360截图20200413093601791.jpg
//服务器
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> 

#define MAX_LISTEN 10
char buf[100];
int ad[10];
struct sockaddr_in server_ip,remote_ip;

int num = 0;

void *thread_fun(void *arg)
{
    while(1)
    {
        printf("read data from client:%s\n",inet_ntoa(remote_ip.sin_addr.s_addr));
        read(ad[(int)arg],buf,100);
        printf("buf is %s\n",buf);
    }
    
    return NULL;
    
}

int main()
{
    
    int server_len,remote_len;
    pthread_t tid[10];
    
    int err,sd,i=0;
    
    sd = socket(AF_INET,SOCK_STREAM,0);
    if(sd == -1)
    {
        printf("create socket failed,errno is %d\n",errno);
        return;
    }
    
    server_ip.sin_family = AF_INET;
    server_ip.sin_port = htons(5678);
    server_ip.sin_addr.s_addr = htonl(INADDR_ANY);
    memset(server_ip.sin_zero,0,8);
    
    err = bind(sd,(struct sockaddr *)(&server_ip),sizeof(struct sockaddr));
    if(err == -1)
    {
        printf("bind error,errno is %d\n",errno);
        close(sd);
        return;
    }
    
    err = listen(sd,MAX_LISTEN);
    if(err == -1)
    {
        printf("listen error, errno is %d\n",errno);
        close(sd);
        return ;
    }
    
    remote_len = sizeof(struct sockaddr);
    while(1)
    {
        ad[i] = accept(sd,(struct sockaddr*)(&remote_ip),&remote_len);
        if(ad[i] == -1)
        {
            printf("accept error,errno is %d\n",errno);
            close(sd);
            return;
        }
        
        err = pthread_create(&tid[i],NULL,thread_fun,(void*)i);
        if(err != 0)
        {
            printf("create new thread failed\n");
            close(ad[i]);
        }
        i++;
        
        
        close(ad[i]);
    }
    
    close(sd);
}
//客户端
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> 

#define MAX_LISTEN 10
char buf[100];
int sd;
struct sockaddr_in server_ip;


void *thread_write(void *arg)
{
    while(1)
    {
        write(sd,"hello",6);
        sleep(1);
    }
    return NULL;
}

void *thread_read(void *arg)
{
    while(1)
    {
        sleep(1);
        memset(buf,0,100);
        read(sd,buf,100);
        printf("client 2 say:%s\n",buf);
    }
    return NULL;
}

int main()
{
    
    int server_len,remote_len;
    pthread_t tid_read,tid_write;
    
    int err,sd,i=0;
    
    sd = socket(AF_INET,SOCK_STREAM,0);
    if(sd == -1)
    {
        printf("create socket failed,errno is %d\n",errno);
        return;
    }
    
    server_ip.sin_family = AF_INET;
    server_ip.sin_port = htons(5678);
    server_ip.sin_addr.s_addr = htonl(INADDR_ANY);
    memset(server_ip.sin_zero,0,8);
    
    err = connect(sd,(struct sockaddr *)(&server_ip),sizeof(struct sockaddr));
    if(err == -1)
    {
        printf("connect error,errno is %d\n",errno);
        close(sd);
        return;
    }
    
    err = pthread_create(&tid_read,NULL,thread_read,NULL);
    if(err)
    {
        printf("create read thread failed\n");
        close(sd);
        return ;
    }
    
    err = pthread_create(&tid_write,NULL,thread_write,NULL);
    if(err)
    {
        printf("create read thread failed\n");
        close(sd);
        return ;
    }
    
    pthread_join(tid_read,NULL);
    pthread_join(tid_write,NULL);
    
    
    close(sd);
}
  • 实现:


    360截图20200413100826000.jpg
    360截图20200413101728877.jpg
    360截图20200413101817019.jpg

相关文章

网友评论

      本文标题:Linux多线程编程

      本文链接:https://www.haomeiwen.com/subject/unqdmhtx.html