27.1线程创建
//创建线程
int pthread_create(pthread_t *thread,
const pthread_attr_t *attr,
void (*start_routine)(void*),
void *arg);
- thread-local变量
__thread int x;
__thread char *s;
类似这种以__thread
定义的变量是线程本地变量 会在创建的每一个线程中都保留一个副本
27.2线程完成
//等待线程结束
int pthread_join(pthread_t thread,void **value_ptr)
//注意其第二个参数的类型是pointer to pointer
pthread_join()
的第二个参数是一个指针,指向希望得到的返回值,如果不需要返回值,那么也可以传入NULL
27.3 锁
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
如果意识到有一段代码是一个临界区,那么就需要通过锁来保护
所有的锁必须正确初始化 以确保他们具有正确的值 并在锁和解锁被调用时按照需要工作
初始化锁:
- ①使用PTHREAD_MUTEX_INITIALIZER
pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER
- ②动态方法 调用pthread_mutex_init()
int rc=pthread_mutex_init(&lock,NULL);
assert(rc==0) //alwasy check success!
第一个参数是锁本身的地址,第二个参数是可选属性
27.4 条件变量
当线程之间必须要发生某种信号时 如果一个线程在等待另一个线程继续执行某些操作,条件变量很有用
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);//使调用线程进入休眠状态
int pthread_cond_signal(pthread_cond_t *cond);
要使用条件变量 必须另外有一个与此条件相关的锁 在调用函数时 要持有这个锁
典型用法:
pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
pthread_mutex_lock(&lock);
while(ready==0)
pthread_cond_wait(&cond,&lock);
pthread_mutex_unlock(&lock);
在初始化相关锁和条件后 一个线程检查变量ready是否已经被设置为0意外的值 如果没有 就调用等待函数休眠 直到其他线程唤醒它
唤醒线程的代码:
pthread_mutex_lock(&lock,NULL);
ready=1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
- 等待调用将锁作为第二个参数 而信号调用只需要一个参数:因为等待调用除了使线程进入睡眠状态外,还会让调用者在睡眠的时候释放锁(不然其他线程怎么获得锁 修改临界区内容从而唤醒该线程捏?)
- 在被唤醒之后、返回之前,pthread_cond_wait()会重新获得该锁 确保整个过程都持有锁
每个线程都有自己的栈:线程的局部变量是线程私有的。线程之间共享数据,值要在堆区或者其他全局可访问的位置:e.g. ①刚刚的例子中ready就是全局变量 ②malloc出来的动态内存是位于堆区的