Linux:线程

线程的实现方式

在操作系统中,线程的实现有以下三种方式:

  1. 内核级线程
  2. 用户级线程
  3. 组合级线程
    在这里插入图片描述
    Linux 中线程的实现

Linux 实现线程的机制非常独特。从内核的角度来说,它并没有线程这个概念。 Linux 把所有的线程都当做进程来实现。内核并没有准备特

别的调度算法或是定义特别的数据结构来表征线程。相反,线程仅仅被视为一个与其他进程共享某些资源的进程。每个线程都拥有唯一隶属

于自己的 task_struct,所以在内核中,它看起来就像是一个普通的进程(只是线程和其他一些进程共享某些资源,如地址空间)。
线程库中的接口介绍

#include <pthread.h>
/*
pthread_create()用于创建线程
thread: 接收创建的线程的 ID
attr: 指定线程的属性
start_routine: 指定线程函数
arg: 给线程函数传递的参数
成功返回 0, 失败返回错误码
*/
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
/*
pthread_exit()退出线程
retval:指定退出信息    向外界传递的参数
*/
int pthread_exit(void *retval);
/*
pthread_join()等待 thread 指定的线程退出,线程未退出时,该方法阻塞
retval:接收 thread 线程退出时,指定的退出信息  
*/
int pthread_join(pthread_t thread, void **retval);
线程同步

​ 线程同步指的是当一个线程在对某个临界资源进行操作时,其他线程都不可以对这个资源进行操作,直到该线程完成操作, 其他线程才

能操作,也就是协同步调,让线程按预定的先后次序进行运行。 线程同步的方法有四种:互斥锁、信号量、条件变量、读写锁。

编写下列程序,将index在五个进程上一起加1000次

#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<pthread.h>

int _index=1;
void *thread_fun(void * arg)
{
    for(int i=0; i<1000; i++)
    {
        printf("_index=%d\n",_index++);
    }
}

int main()
{
    pthread_t id[5];
    int i=0;
    for(;i<5; i++ )
    {
        pthread_create(&id[i],NULL,thread_fun,NULL);
    }

    for(i=0; i<5; i++)
    {
        pthread_join(id[i],NULL);
    }
    exit(0);
}

第一次运行:
在这里插入图片描述

第二次运行:
在这里插入图片描述

第三次运行:
在这里插入图片描述
说明线程在对index的加操作上不是完全独立的,如果两个线程同时对index进行加操作,那index的值增加就会少一次,所以每次运行的值都不一样。

对程序添加上信号量,每个线程进行index加操作都要PV操作,这样index值就会固定,线程就同步了

#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<pthread.h>
#include<semaphore.h>

sem_t sem;
int _index=1;
void *thread_fun(void * arg)
{
    for(int i=0; i<1000; i++)
    {
        sem_wait(&sem);//P
        printf("_index=%d\n",_index++);
        sem_post(&sem);//V
    }
}

int main()
{
    sem_init(&sem,0,1);
    pthread_t id[5];
    int i=0;
    for(;i<5; i++ )
    {
        pthread_create(&id[i],NULL,thread_fun,NULL);
    }

    for(i=0; i<5; i++)
    {
        pthread_join(id[i],NULL);
    }
    exit(0);
    sem_destroy(&sem);
}

运行结果:
在这里插入图片描述
互斥锁

#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *attr);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_destroy(pthread_mutex_t *mutex);

信号量

#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
int sem_wait(sem_t *sem);
int sem_post(sem_t *sem);
int sem_destroy(sem_t *sem);

条件变量

#include <pthread.h>
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *attr);
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_cond_signal(pthread_cond_t *cond); //唤醒单个线程
int pthread_cond_broadcast(pthread_cond_t *cond); //唤醒所有等待的线程
int pthread_cond_destroy(pthread_cond_t *cond);

读写锁

#include <pthread.h>
int pthread_rwlock_init(pthread_rwlock_t *rwlock, pthread_rwlockattr_t *attr);
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
线程安全

多线程程序无论调度顺序怎样,都能得到一个正确的结果,就处于一个线程安全状态

要保证线程安全需要做到:

1) 对线程同步,保证同一时刻只有一个线程访问临界资源。

2) 在多线程中使用线程安全的函数(可重入函数),所谓线程安全的函数指的是:如果一个

函数能被多个线程同时调用且不发生竟态条件,则我们程它是线程安全的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小新 蜡笔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值