一、什么叫线程,为什么要引入线程
二、线程的表示
与PID类似,线程有线程ID,类型为pthread_t,注意不能作为整数处理。如果要比较两个线程ID是否相同,要使用函数:
int pthread_equal(pthread_t tid1, pthread_t tid2)
另
pthread_t pthread_self(void)
可以得到当前线程的线程ID。
三、创建线程
线程创建函数:
int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr
void *(*start_trn)(void*), void *restrict arg)
tidp返回线程ID,attr是线程属性,start_trn为线程的起始地址,arg为线程函数的参数
线程与进程不同的一点在于,父进程结束后,子进程不一定结束;但主线程退出时,子线程一定跟着退出。
四、终止线程
如果线程调用exit,_Exit或_exit,会终止整个进程。而如果要单个线程终止,有三种方法:
1. 线程从启动例程中返回,返回值为线程的退出码;
2. 线程被同一进程中的其他线程取消;
3. 线程调用pthread_exit。
pthread_exit的原型为:
void pthread_exit(void *rval_ptr)
其他进程可以通过pthread_join函数访问到rval_ptr(有什么作用?)
int pthread_join(pthread_t thread, void **rval_ptr)
这样调用线程一直阻塞,直到thread终止。
五、线程同步
1. 互斥量机制
线程A使用某一资源时,先对互斥量加锁,其他线程也对此互斥量加锁时,发现他已经加锁,则自己阻塞,直到线程A释放了锁。互斥量又pthread_mutex_t表示。
int pthread_mutex_init(pthread_mutex_t *restric mutex,
const pthread_mutexattr_t *restrict attr)
初始化互斥量。
如果pthread_mutex_t是动态分配的(malloc),那么free前,要调用pthread_mutex_destroy
int pthread_mutex_destroy(pthread_mutex_t *mutex)
对互斥量加锁:
int pthread_mutex_lock(pthread_mutex_t *mutex)
对互斥量解锁:
int pthread_mutex_unlock(pthread_mutex_t *mutex)
而函数pthread_mutex_trylock则是尝试对互斥量加锁,如果已经被锁,则返回0而不会阻塞。
使用互斥量时,要避免死锁的情况(有多个互斥量容易造成死锁)。
2. 读写锁
读写锁比互斥量高端。互斥量只能使一个线程加锁或不加锁。而读写锁有三种模式:读模式下加锁(每次只能一个线程),写模式下加锁(多个线程),不加锁。读写锁用pthread_rwlock_t表示。
初始化读写锁:
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,
const pthread_rwlockattr_t *restrict attr)
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
读加锁:
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_tryrdlock(pthread_rwlock_t *rwlock)
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock)
3. 条件变量
条件变量用pthread_cond_t表示
条件变量初始化:
int pthread_cond_init(pthread_cond_t *restrict cond,
pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t *cond)
等待条件成真:
int pthread_cond_wait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex)
调用线程先将互拆量锁住 ,然后调用此函数并把被锁住的互斥量传入,函数把调用线程放到等待条件的线程列表上,然后对互拆量解锁,使别的线程相继可以入到等待条件的线程列表上。所以,条件变量和互斥量是配合使用的。
int pthread_cond_timewait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex,
const struct timespec *restric timeout)
此函数指定了个时间,指明线程等待多长时间。
下面两个函数通知线程条件已满足:
int pthread_cond_signal(pthread_cond_t *cond)
唤醒等待该条件的某个线程;
int pthread_cond_broadcast(pthread_cond_t *cond)
唤醒等待该条件的所有线程。
六、gcc编译多线程程序时要加上-lpthread参数,否则会提示找不到pthread_create…的引用。