线程的创建:
该函数会在进程中创建一个新线程,函数的各参数描述如下:
o 第一个参数thread是一个指向pthread_t对象的指针,当线程成功创建后,新线程
的ID会存储在thread指向的pthread_t对象中。
o 第二个参数attr,指定新建线程的属性。如果attr为NULL,则创建线程时使用默认的属
性。线程创建完成之后仍可使用相关函数来改变线程的属性,
o 第三个参数start_routine是一个函数指针(即函数的首地址),它是新建线程的入口,新
创建的线程从start_routine这个地址开始运行。从上面的定义来看,该函数指针所指向
的函数有两个特征:
函数返回值为 void * 类型
该函数有一个类型为 void * 类型的参数
o 第四个参数arg。start_routine所指向的函数有一个类型为 void * 的参数,即为这里
的 void *arg
返回值:
如果线程创建成功,则pthread_create函数返回0;否则返回一个非0值,该非0值是代
表一个错误码来指示出错类型。
形 参: thread 被等待的线程标识符 retval 一个用户定义的指针,它可以用来存储被等待线程的返回值 说 明:这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。
通过锁的机制实现线程间的互斥,同一时刻只有一个线程可以锁定它,当一个锁被某个线程锁定的时候,如果有另外一个线程尝试锁定这个临界区(互斥体),则第二个线程会被阻塞,或者说被置于等待状态。只有当第一个线程释放了对临界区的锁定,第二个线程才能从阻塞状态恢复运行。
--------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------
int pthread_create(pthread_t *restrict thread,
const pthread_attr_t *restrict attr,
void *(*start_routine)(void *),
void *restrict arg
);
o 第一个参数thread是一个指向pthread_t对象的指针,当线程成功创建后,新线程
的ID会存储在thread指向的pthread_t对象中。
o 第二个参数attr,指定新建线程的属性。如果attr为NULL,则创建线程时使用默认的属
性。线程创建完成之后仍可使用相关函数来改变线程的属性,
o 第三个参数start_routine是一个函数指针(即函数的首地址),它是新建线程的入口,新
创建的线程从start_routine这个地址开始运行。从上面的定义来看,该函数指针所指向
的函数有两个特征:
函数返回值为 void * 类型
该函数有一个类型为 void * 类型的参数
o 第四个参数arg。start_routine所指向的函数有一个类型为 void * 的参数,即为这里
的 void *arg
返回值:
如果线程创建成功,则pthread_create函数返回0;否则返回一个非0值,该非0值是代
表一个错误码来指示出错类型。
等待线程结束函数:
int pthread_join(pthread_t thread, void **retval);
形 参: thread 被等待的线程标识符 retval 一个用户定义的指针,它可以用来存储被等待线程的返回值 说 明:这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。
线程终止函数:
void pthread_exit(void* retval);
retval 函数的返回指针,只要pthread_join中的第二个参数retval不是NULL,这个值将被传递给retval。
线程取消函数:
int pthread_cancel(pthread_t thread);
成功返回0;失败返回错误码。
通过锁的机制实现线程间的互斥,同一时刻只有一个线程可以锁定它,当一个锁被某个线程锁定的时候,如果有另外一个线程尝试锁定这个临界区(互斥体),则第二个线程会被阻塞,或者说被置于等待状态。只有当第一个线程释放了对临界区的锁定,第二个线程才能从阻塞状态恢复运行。
int pthread_mutex_init(pthread_mutex_t* mutex, const thread_mutexattr_t* mutexattr);初始化一个互斥锁。
参数:
mutex:互斥锁地址。类型是 pthread_mutex_t 。
attr:设置互斥量的属性,通常可采用默认属性,即可将 attr 设为 NULL。
可以使用宏 PTHREAD_MUTEX_INITIALIZER 静态初始化互斥锁,比如:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
这种方法等价于使用 NULL 指定的 attr 参数调用 pthread_mutex_init() 来完成动态初始化,不同之处在于 PTHREAD_MUTEX_INITIALIZER 宏不进行错误检查。
返回值:
成功:0,成功申请的锁默认是打开的。
失败:非 0 错误码
int pthread_mutex_lock(pthread_mutex_t* mutex);如果mutex被锁定,当前进程处于等待状态;否则,本进程获得互斥锁并进入临界区。
参数:
mutex:互斥锁地址。
返回值:
成功:0
失败:非 0 错误码
int pthread_mutex_trylock(pthread_mutex_t* mutex);
和lock不同的时候,尝试获得互斥锁不成功不会使得进程进入阻塞状态,而是继续返回线程执行。该函数可以有效避免循环等待锁,如果trylock失败可以释放已经占有的资源,这样可以避免死锁。
调用该函数时,若互斥锁未加锁,则上锁,返回 0;若互斥锁已加锁,则函数直接返回失败,即 EBUSY。
int pthread_mutex_unlock(pthread_mutex_t* mutex);
释放互斥锁,并使得被阻塞的线程获得互斥锁并执行。
参数:
mutex:互斥锁地址。
返回值:
成功:0
失败:非 0 错误码
int pthread_mutex_destroy(pthread_mutex_t* mutex);用来撤销互斥锁的资源
参数:
mutex:互斥锁地址。
返回值:
成功:0
失败:非 0 错误码
--------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
pthread_mutex_t mutex; //互斥锁
void printer(char *str)
{
pthread_mutex_lock(&mutex); //上锁
while(*str!='\0')
{
putchar(*str);
fflush(stdout);
str++;
sleep(1);
}
printf("\n");
pthread_mutex_unlock(&mutex); //解锁
}
// 线程一
void *thread_fun_1(void *arg)
{
char *str = "hello";
printer(str);
}
// 线程二
void *thread_fun_2(void *arg)
{
char *str = "world";
printer(str);
}
int main(void)
{
pthread_t tid1, tid2;
pthread_mutex_init(&mutex, NULL); //初始化互斥锁
// 创建 2 个线程
pthread_create(&tid1, NULL, thread_fun_1, NULL);
pthread_create(&tid2, NULL, thread_fun_2, NULL);
// 等待线程结束,回收其资源
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
pthread_mutex_destroy(&mutex); //销毁互斥锁
return 0;
}
测试如下:
gcc 1.c -lpthread 编译
[root@libmaster zxd]# ./a.out
hello
world
不加锁打印:
[root@libmaster zxd]# ./a.out
hwoerllldo