UNIX 线程基础

线程概念

UNIX 进程可以看做是只有一个控制线程;一个进程在某一时刻只能做一件事情。但是有了多个线程以后,在设计程序时就可以把进程设计成在某一时刻能够做不止一件事情,每个线程各自独立的任务。这样的优势

  • 可以通过每个事件类型分配单独处理线程,可以简化异步事件的代码;
  • 多个进程内存和文件描述符共享比较麻烦,而多个线程是共享同一个进程的内存空间的;
  • 有些问题可以分解,来提高程序的吞吐量;
  • 交互程序可以通过多线程来改善响应时间。
    一个进程的所有信息对该进程的所有线程都是共享的,包括代码、程序的全局内存,堆内存,栈,以及文件描述符。
    当然每个线程也有执行环境必须的信息。
    在这里插入图片描述

接口函数

线程创建pthread_create

在一个线程中创建一个新的线程会使用到pthread_create,函数原型如下

       #include <pthread.h>

       int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                          void *(*start_routine) (void *), void *arg);
       // thread  新建线程ID存储的地址指针
       // attr    用于定制各种不同的线程属性
	  // start_routine     //新建线程的函数指针地址
	  // arg               新线程的传入参数
	  // 返回值 成功返回0,否则返回错误编号errno

线程终止pthread_exit

在一个线程使用进程终止函数exit,_Exit,_exit,那么整个进程都会终止。
再不终止整个进程的情况下,单个线程有三种退出方式,如下:

  • 从启动例程中返回,返回值是线程退出码;
  • 线程可以被同一进程中其他线程取消;
  • 线程调用pthread_exit
    函数原型如下
       #include <pthread.h>

       void pthread_exit(void *retval);
       int pthread_join(pthread_t thread, void **retval);  //返回值 成功返回0,否则返回错误编号errno

		

pthread_join 函数用于获取线程返回值,可以恢复资源。
线程中可以通过调用pthread_cancel函数来请求取消同一进程中的其他线程。

       #include <pthread.h>

       int pthread_cancel(pthread_t thread);
		//返回值 成功返回0,否则返回错误编号errno

在这里插入图片描述

线程同步

当多个线程共享相同的内存时,需要确保每个线程看到一致的数据视图。并不会出现多个线程访问一个数据,其值不一样的情况。

互斥量

可以使用pthread 的互斥接口来保护数据,确保同一时间是有一个线程访问数据。互斥量从本质上来说就是一把锁,在访问共享资源之前进行加锁,访问之后进行解锁。加锁之后其他线程在进行访问都会被阻塞,直到解锁。
这些函数原型如下:

     #include <pthread.h>

       pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;

       pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;

       pthread_mutex_t errchkmutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;

       int  pthread_mutex_init(pthread_mutex_t  *mutex,  const  pthread_mutex‐
       attr_t *mutexattr);

       int pthread_mutex_lock(pthread_mutex_t *mutex);

       int pthread_mutex_trylock(pthread_mutex_t *mutex);

       int pthread_mutex_unlock(pthread_mutex_t *mutex);

       int pthread_mutex_destroy(pthread_mutex_t *mutex);

避免死锁

参照这篇文章死锁

读写锁

读写锁和互斥量类似,不过允许更高的并行性。读写锁有三种状态,读模式加锁,写模式加锁,不加锁的状态。一次只有一个线程可以占有写模式的读写锁,但是多个线程可以同时读模式的读写锁。

       #include <pthread.h>

       int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);   // 销毁锁
       int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,
           const pthread_rwlockattr_t *restrict attr);   // 读写锁初始化
       pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;   //静态初始化


/ //返回值 成功返回0,否则返回错误编号errno

       int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);   //读的模式加锁
       int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock); //检查读锁
       int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);   // 写的模式加锁
       int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);   // 检查写锁
       int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);    //j解锁

//返回值 成功返回0,否则返回错误编号errno

条件变量

条件变量是线程的另外一种同步机制一般和互斥量一起使用。条件变量本身是由互斥量保护的。

       #include <pthread.h>

       pthread_cond_t cond = PTHREAD_COND_INITIALIZER;   // 条件变量静态初始化

       int    pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t*cond_attr); //条件变量动态初始化

       int pthread_cond_signal(pthread_cond_t *cond);  //唤醒等待该条件的线程

       int pthread_cond_broadcast(pthread_cond_t *cond); //唤醒等待该条件的所有线程

       int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); //等待条件变量满足

       int   pthread_cond_timedwait(pthread_cond_t   *cond,    pthread_mutex_t
       *mutex, const struct timespec *abstime);

       int pthread_cond_destroy(pthread_cond_t *cond);  //条件变量反初始化,回收资源

//返回值 成功返回0,否则返回错误编号errno

自旋锁

自旋锁与互斥量类似,但他不是通过休眠让进程阻塞,而是在获取锁之前一直处于忙等的阻塞状态。
一般使用于以下情况:锁被持有时间短,而且线程并不希望在重新调度上花费太多的成本。

       #include <pthread.h>

       int pthread_spin_destroy(pthread_spinlock_t *lock);
       int pthread_spin_init(pthread_spinlock_t *lock, int pshared);
       int pthread_spin_lock(pthread_spinlock_t *lock);
       int pthread_spin_unlock(pthread_spinlock_t *lock);
       int pthread_spin_trylock(pthread_spinlock_t *lock);

//返回值 成功返回0,否则返回错误编号errno

屏障

屏障用于协调多个线程并行工作的同步机制。屏障允许每个线程等待,知道所有的线程都到达某一点,然后从该点继续执行。像pthread_jion函数。

       #include <pthread.h>

       int pthread_barrier_destroy(pthread_barrier_t *barrier);
       int pthread_barrier_init(pthread_barrier_t *restrict barrier,
           const pthread_barrierattr_t *restrict attr, unsigned count); // count屏蔽线程的数量
           
       int pthread_barrier_wait(pthread_barrier_t *barrier);   //屏蔽计数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值