与线程自身相关API
1.线程的创建(代码编译时需要在后面+lpthread)
例:gcc xxx.c -lpthread
#include <pthread.h>
int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
// 返回:若成功返回0,否则返回错误编号
当pthread_create成功返回时,由tidp指向的内存单元被设置为新创建线程的线程ID。attr参数用于定制各种不同的线程属性,暂可以把它设置为NULL,以创建默认属性的线程
2. 线程退出
单个线程可以通过以下三种方式退出,在不终止整个进程的情况下停止它的控制流:
1)线程只是从启动例程中返回,返回值是线程的退出码。
2)线程可以被同一进程中的其他线程取消。
3)线程调用pthread_exit:
#include <pthread.h>
#include <stdio.h>
//#include <pthread.h>
//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
void *func1(void *arg)
{
printf("t1 :%ld thread is create \n",(unsigned long)pthread_self());
printf("t1 of param :%d \n",*((int*)arg));
}
int main()
{
int ret;
pthread_t t1;
int param = 100;
ret = pthread_create(&t1,NULL,func1,(void *)¶m);
if(ret == 0){
printf("main:create t1 success \n");
}
printf("main :%ld \n",(unsigned long)pthread_self());
pthread_join(t1,NULL);
return 0;
}
代码实现
main:create t1 success
main :139801943803712
t1 :139801935279872 thread is create
t1 of param :100
3. 线程等待
#include <pthread.h>
int pthread_join(pthread_t thread, void **rval_ptr);
// 返回:若成功返回0,否则返回错误编号
如果对线程的返回值不感兴趣,可以把rval_ptr置为NULL
#include <pthread.h>
#include <stdio.h>
//#include <pthread.h>
//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
void *func1(void *arg)
{
static char *p = "t1 is running";
printf("t1 :%ld thread is create \n",(unsigned long)pthread_self());
printf("t1 of param :%d \n",*((int*)arg));
pthread_exit((void*)p);
}
int main()
{
int ret;
pthread_t t1;
int param = 100;
ret = pthread_create(&t1,NULL,func1,(void *)¶m);
char *pret;
if(ret == 0){
printf("main:create t1 success \n");
}
printf("main :%ld \n",(unsigned long)pthread_self());
pthread_join(t1,(void **)&pret);
printf("main t1 quit :%s \n",pret);
return 0;
}
线程共享内存空间的代码验证
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
//#include <pthread.h>
//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
int g_data = 0;
void *func1(void *arg)
{
printf("t1 :%ld thread is create \n",(unsigned long)pthread_self());
printf("t1 of param :%d \n",*((int*)arg));
while(1){
printf("t1 :%d\n",g_data++);
sleep(1);
}
}
void *func2(void *arg)
{
printf("t2 :%ld thread is create \n",(unsigned long)pthread_self());
printf("t2 of param :%d \n",*((int*)arg));
while(1){
printf("t2 :%d\n",g_data++);
sleep(1);
}
}
int main()
{
int ret;
pthread_t t1;
pthread_t t2;
int param = 100;
ret = pthread_create(&t1,NULL,func1,(void *)¶m);
if(ret == 0){
printf("main:create t1 success \n");
}
ret = pthread_create(&t2,NULL,func2,(void *)¶m);
if(ret == 0){
printf("main:create t2 success \n");
}
printf("main :%ld \n",(unsigned long)pthread_self());
while(1)
{
printf("main %d \n",g_data++);
sleep(1);
}
pthread_join(t1,NULL);
pthread_join(t2,NULL);
return 0;
}
~
代码实现
main:create t1 success
main:create t2 success
t1 :140592171341568 thread is create
t1 of param :100
t1 :0
main :140592179865408
main 1
t2 :140592162948864 thread is create
t2 of param :100
t2 :2
main 3
t1 :4
t2 :5
t1 :6
t2 :8
main 7
main 9
t1 :10
t2 :11
main 12
t1 :13
t2 :14
与互斥锁相关API
互斥量(mutex)从本质上来说是一把锁,在访问共享资源前对互斥量进行加锁,在访问完成后释放互斥量上的锁。对互斥量进行加锁后,任何其他试图再次对互斥量加锁的线程将会被阻塞直到当前线程释放该互斥锁。如果释放互斥锁时有多个线程阻塞,所有在该互斥锁上的阻塞线程都会变成可运行状态,第一个变为可运行状态的线程可以对互斥量加锁,其他线程将会看到互斥锁依然被锁住,只能回去等待它重新变为可用。在这种方式下,每次只有一个线程可以向前运行。
1. 创建及销毁互斥锁
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destroy(pthread_mutex_t mutex);
// 返回:若成功返回0,否则返回错误编号
要用默认的属性初始化互斥量,只需把attr设置为NULL
2. 加锁及解锁、
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t mutex);
int pthread_mutex_trylock(pthread_mutex_t mutex);
int pthread_mutex_unlock(pthread_mutex_t mutex);
// 返回:若成功返回0,否则返回错误编号
出现死锁的问题:是因为首先会有两个锁,线程一获取锁a的同时获取锁b,线程二获取锁b时获取锁a,从而线程一获取不到锁b,线程而获取不到锁a,线程一拿到了锁a,线程而拿到了锁b,所以线程一拿不到锁b,线程二拿不到锁a,从而都进行等待
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
//#include <pthread.h>
//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
int g_data = 0;
pthread_mutex_t mutex;
void *func1(void *arg)
{
int i;
pthread_mutex_lock(&mutex);
for(i=0;i<5;i++){
printf("t1 :%ld thread is create \n",(unsigned long)pthread_self());
printf("t1 of param :%d \n",*((int*)arg));
sleep(1);
}
pthread_mutex_unlock(&mutex);
}
void *func2(void *arg)
{
pthread_mutex_lock(&mutex);
printf("t2 :%ld thread is create \n",(unsigned long)pthread_self());
printf("t2 of param :%d \n",*((int*)arg));
pthread_mutex_unlock(&mutex);
}
int main()
{
int ret;
pthread_t t1;
pthread_t t2;
pthread_mutex_init(&mutex,NULL); //mutex初始化
int param = 100;
ret = pthread_create(&t1,NULL,func1,(void *)¶m);
if(ret == 0){
printf("main:create t1 success \n");
}
ret = pthread_create(&t2,NULL,func2,(void *)¶m);
if(ret == 0){
printf("main:create t2 success \n");
}
printf("main :%ld \n",(unsigned long)pthread_self());
pthread_join(t1,NULL);
pthread_join(t2,NULL);
pthread_mutex_destroy(&mutex);
return 0;
}
代码实现
main:create t1 success
main:create t2 success
main :139813046646592
t1 :139813038122752 thread is create
t1 of param :100
t1 :139813038122752 thread is create
t1 of param :100
t1 :139813038122752 thread is create
t1 of param :100
t1 :139813038122752 thread is create
t1 of param :100
t1 :139813038122752 thread is create
t1 of param :100
t2 :139813029730048 thread is create
t2 of param :100
与条件变量相关API
条件变量是线程另一可用的同步机制。条件变量给多个线程提供了一个会合的场所。条件变量与互斥量一起使用时,允许线程以无竞争的方式等待特定的条件发生。
1. 创建及销毁条件变量
#include <pthread.h>
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t cond);
// 返回:若成功返回0,否则返回错误编号
除非需要创建一个非默认属性的条件变量,否则pthread_cont_init函数的attr参数可以设置为NULL。
2. 等待
#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, cond struct timespec *restrict timeout);
// 返回:若成功返回0,否则返回错误编号
pthread_cond_timedwait函数的工作方式与pthread_cond_wait函数类似,只是多了一个timeout。timeout指定了等待的时间,它是通过timespec结构指定。
3. 触发
#include <pthread.h>
int pthread_cond_signal(pthread_cond_t cond);
int pthread_cond_broadcast(pthread_cond_t cond);
// 返回:若成功返回0,否则返回错误编号
结合代码做一个小工程
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
//#include <pthread.h>
//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
int g_data = 0;
pthread_mutex_t mutex;
pthread_cond_t cond;
void *func1(void *arg)
{
printf("t1 :%ld thread is create \n",(unsigned long)pthread_self());
printf("t1 of param :%d \n",*((int*)arg));
while(1){
pthread_cond_wait(&cond,&mutex);
printf("t1 quit ================\n");
printf("t1 :%d\n",g_data);
sleep(1);
g_data = 0;
}
}
void *func2(void *arg)
{
printf("t2 :%ld thread is create \n",(unsigned long)pthread_self());
printf("t2 of param :%d \n",*((int*)arg));
while(1){
printf("t2 :%d\n",g_data);
pthread_mutex_lock(&mutex);
g_data++;
if(g_data ==3){
pthread_cond_signal(&cond);
}
pthread_mutex_unlock(&mutex);
sleep(1);
}
}
int main()
{
int ret;
int param =100;
pthread_t t1;
pthread_t t2;
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cond,NULL);
ret = pthread_create(&t1,NULL,func1,(void *)¶m);
ret = pthread_create(&t2,NULL,func2,(void *)¶m);
// printf("main :%ld \n",(unsigned long)pthread_self());
pthread_join(t1,NULL);
pthread_join(t2,NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
return 0;
}
t2 :139787529230080 thread is create
t2 of param :100
t2 :0
t1 :139787537622784 thread is create
t1 of param :100
t2 :1
t2 :2
t1 quit ================
t1 :3
t2 :3
t2 :1
t2 :2
t1 quit ================
t1 :3
t2 :3
t2 :1
t2 :2
t1 quit ================