1. 线程与进程
线程拥有自己的栈,与主线程共享全局变量。
进程的时间调度是完全独立的,一个进程内的线程共享进程获得的时间片。
2._REENTRANT 宏
可以使库函数和 errno 变成线程可重入函数。
3. 线程基本函数
需要头文件 #include
3.1 int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
参数说明: thread:指向pthread_create类型的指针,用于引用新创建的线程。
attr:用于设置线程的属性,一般不需要特殊的属性,所以可以简单地设置为NULL。 *
(*start_routine)(void *):传递新线程所要执行的函数地址。 arg:新线程所要执行的函数的参数。 调用如果成功,则返回值是0,如果失败则返回错误代码。
3.2 void pthread_exit(void *retval);
参数说明: retval:返回指针,指向线程向要返回的某个对象。 4
线程通过调用pthread_exit函数终止执行,并返回一个指向某对象的指针。
注意:绝不能用它返回一个指向局部变量的指针,因为线程调用该函数后,这个局部变量就不存在了,这将引起严重的程序漏洞。
3.3 int pthread_join(pthread_t th, void **thread_return);
参数说明: th:将要等待的线程句柄,线程通过pthread_create返回的标识符来指定。
thread_return:一个二级指针,指向另一个指针,而后者指向线程的返回值。
主线程通过调用pthread_join来等待线程结束。
4. 线程同步
线程的同步一般用信号量和互斥量来进行,两种方法使用上差不多,只是理解上面不太一样。对于实际情况,可能选择其中一个更符合问题语义。
4.1 用信号量来同步
int sem_init(sem_t *sem, int pshared, unsigned int value);
参数说明: sem:信号量对象。
pshared:控制信号量的类型,0表示这个信号量是当前进程的局部信号量,否则,这个信号量就可以在多个进程之间共享。
value:信号量的初始值
int sem_post(sem_t *sem);
以原子操作对信号量+1;
int sem_wait(sem_t *sem);
以原子操作对信号量-1; 如果当前信号量是0,则会等待,直到别的线程将信号量变为非0.
int sem_destory(sem_t *sem);
试图销毁信号量,如果信号量有线程在使用,则会返回错误。
用信号量同步的示例代码
void takeMoney_threadsafe(char * token)
{
sem_wait(&sem);
if (money <= 0)
{
sem_post(&sem);
return;
}
printf("%s read %d", token, money);
usleep(50);
money--;
printf(" left %d,\n", money);
sem_post(&sem);
usleep (1);
}
4.2 用互斥量来同步
互斥量使用的函数和信号量非常相似。
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t, *mutexattr);
int pthread_mutex_lock(pthread_mutex_t *mutex);
锁住代码段,当有线程持有互斥锁时,别的线程不能进入这段代码。
int pthread_mutex_unlock(pthread_mutex_t *mutex);
持有锁的线程完成工作后用unlock解锁,其他线程就可以进入这段代码。
int pthread_mutex_destory(pthread_mutex_t *mutex);
销毁互斥量。
用互斥量来同步的代码示例
void takeMoney_threadsafe(char * token)
{
//sem_wait(&sem);
pthread_mutex_lock(&mutex);
if (money <= 0)
{
// sem_post(&sem);
pthread_mutex_unlock(&mutex);
return;
}
printf("%s read %d", token, money);
usleep(50);
money--;
printf(" left %d,\n", money);
// sem_post(&sem);
pthread_mutex_unlock(&mutex);
usleep (1);
}