关于线程

code from <UNIX 高级编程第二版>

一个进程中的所有线程都可以访问该进程的组成部件,如文件描述符和内存。

pthread_t的数据类型表示线程ID

func1.    pthread_t pthread_self(void)

返回线程ID

func2.    int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict_attr,void*(*start_rtn)(void*),void *restrict arg)      创建成功则返回0,否则返回错误编号

restrict,C语言中的一种类型限定符,用于告诉编译器,对象已经被指针所引用,不能通过除该指针外所有其他直接或间接的方式修改该对象的内容

第一个参数为指向线程标识符的指针

第二个参数用来设置线程属性

第三个参数是创建线程起始的运行函数

第四个参数是运行函数的参数

(void*)无类型指针,也可以认为是任意类型指针,其他任意类型的指针如int*等都可以转化成(void*)类型指针

单个线程的三种退出方式,在不终止整个进程的情况下停止它的控制流

(1)线程只是从启动例程中返回,返回值是线程的退出码

(2)线程可以被同一进程中的其他线程取消

(3)线程调用pthread_exit;

func3: void pthread_exit(void *rual_ptr)

参数rual_ptr与传给启动例程的单个参数类似。进程中的其他线程可以通过调用pthread_join这个函数访问到这个指针

func4: int pthread _join(phread_t thread,void  ** rual_ptr )     若成功则返回0,否则返回错误编号

调用线程将一直阻塞,直到指定的线程调用pthread_exit、从启动例程中返回或者被取消。

获取已终止线程的退出码:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

void* thr_fn1(void* arg)
{
    printf("thread 1 return ");
    return ((void*)1);
}

void* thr_fn2(void* arg)
{
    printf("thread 2 exit ");
    pthread_exit((void*)2);
}

int main()
{
    pthread_t ntid1,ntid2;
    int err;
    void * tret;
    err = pthread_create(&ntid1,NULL,thr_fn1,NULL);
    if(err != 0)
    {
        printf("can not create thread 1 ");
    }
    err = pthread_create(&ntid2,NULL,thr_fn2,NULL);
    if(err != 0)
    {
        printf("can not create thread 2 ");
    }
    err = pthread_join(ntid1,&tret);
    if(err != 0)
    {
        printf("can not join thread 1");
    }
    printf("thread 1 exit code is %d ",(int)tret);

        err = pthread_join(ntid2,&tret);
    if(err != 0)
    {
        printf("can not join thread 2");
    }
    printf("thread 2 exit code is %d ",(int)tret);
    exit(0);
}

func5:       itn phread_cancel(pthread_t tid)    返回值为0则成功 

线程可以通过调用上述函数来请求取消同一进程中的其他线程。但只是请求,不一定响应。

互斥量与线程同步

互斥量的本质是为了实现原子操作

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

int tickets = 10;
pthread_mutex_t lock;

void* thread(void*arg)
{
    while(tickets > 0)
    {
        //pthread_mutex_lock(&lock);
        if(tickets > 0)
        {
            usleep (100*1000);
            tickets --;
            printf("%s sold tickets %d ",arg,tickets);
        }
        //pthread_mutex_unlock(&lock);
    }
    return (void*)1;
}


int main()
{
    pthread_t tid1,tid2;
    pthread_mutex_init(&lock,NULL);
    int ret;
    char*name = "the first :";
    void* tret;
    ret = pthread_create(&tid1,NULL,thread,(void*)name);
    if(ret != 0)
    {
        printf("creat thread1 failed! ");
    }
    name = "the second :";
    ret = pthread_create(&tid2,NULL,thread,(void*)name);
    if(ret != 0)
    {
        printf("creat thread2 failed! ");
    }
    ret = pthread_join(tid1,&tret);
    if(ret != 0)
    {
        printf("can not join thread 1");
    }

        ret = pthread_join(tid2,&tret);
    if(ret != 0)
    {
        printf("can not join thread 2");
    }
    exit(0);
}

未加锁时结果如下:

加锁的结果:

未加锁时虽然ticket已经减到0了,但另一线程几乎同时走到了sleep的部分,于是再自减1得到-1的结果,加锁后则不会出现这样的情况,另一线程必须等到锁被unlock,才能继续走下去。

原文地址:https://www.cnblogs.com/doulcl/p/10461497.html