线程包含于进程中,是进程的实际运作单位。一个进程中可包含有多个线程,所有线程共用同一块资源,同样的一个线程的错误会导致整个进程出现问题。使用线程是因为线程的开销远小于进程,同时进程之间数据的通信相对复杂,而线程共用相同空间,会方便很多。
多线程目前在Linux平台上有成熟的pthread库,其主要开发分为三块,线程,互斥锁和条件。
1.线程操作:创建,退出,等待。
API:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
pthread_create:第一个参数为线程的ID,第二个参数是线程的属性(可设置为NULL,默认),第三个参数是线程具体做什么的函数指针,第四个参数是线程需要传的参数(多个参数需要传入用结构体)。
int pthread_exit(void *rval_ptr);
pthread_exit:参数为要返回的数据,要求是static。不然结束之后栈就没了。
int pthread_join(pthread_t thread, void **rval_ptr);
pthread_join:第一个参数为等待哪一个线程,第二个参数是pthread_exit返回的数据存入哪里。
#include <pthread.h>
#include <stdio.h>
void *func1(void *arg)
{
static char *ret = "it is a test!";
printf("t1: %ld , thread is created\n", (unsigned long)pthread_self());
printf("t1:parame get %d\n",*((int *)arg));
pthread_exit((void *)ret);
}
int main()
{
pthread_t t1;
int parame = 55;
int ret;
char *pstr = NULL;
ret = pthread_create(&t1, NULL, func1, (void *)¶me);
if(ret == 0){
printf("main :thread create success\n");
}
printf("main : thred %ld\n", (unsigned long)pthread_self());
pthread_join(t1, (void **)&pstr);
printf("func1 return is : %s\n", pstr);
return 0;
}
2.互斥锁:创建,加锁,解锁,销毁
互斥量(mutex)就是一把锁,在访问资源前对互斥量加锁,访问结束后解锁。互斥量在使用时需要进行初始化,也可以静态分配为(PTHREAD_MUTEX_INITIALIZER)。
API:
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
pthread_mutex_init:第一个参数为要操作哪一个互斥量,第二个参数为属性,写NULL默认。
int pthread_mutex_lock(pthread_mutex_t *mutex);
pthread_mutex_lock:参数为互斥量地址。
int pthread_mutex_unlock(pthread_mutex_t *mutex);
pthread_mutex_unlock:参数为互斥量地址。
int pthread_mutex_destroy(pthread_mutex_t mutex);
pthread_mutex_destroy:参数为互斥量地址。
#include <pthread.h>
#include <stdio.h>
int data = 0;
pthread_mutex_t mutex1;
void *func1(void *arg)
{
pthread_mutex_lock(&mutex1);
printf("t1: %ld , thread is created\n", (unsigned long)pthread_self());
printf("t1:parame get %d\n",*((int *)arg));
while(1){
printf("t1 : %d\n", data++);
sleep(1);
if(data == 3){
printf("3 qiut ///\n");
pthread_mutex_unlock(&mutex1);
pthread_exit(NULL);
}
}
}
void *func2(void *arg)
{
printf("t2: %ld , thread is created\n", (unsigned long)pthread_self());
printf("t2:parame get %d\n",*((int *)arg));
while(1){
printf("t2: %d\n", data);
pthread_mutex_lock(&mutex1);
data++;
pthread_mutex_unlock(&mutex1);
sleep(1);
}
}
int main()
{
pthread_t t1;
pthread_t t2;
int parame = 55;
int ret;
char *pstr = NULL;
pthread_mutex_init(&mutex1, NULL);
ret = pthread_create(&t1, NULL, func1, (void *)¶me);
if(ret == 0){
printf("main :thread1 create success\n");
}
ret = pthread_create(&t2, NULL, func2, (void *)¶me);
if(ret == 0){
printf("main :thread2 create success\n");
}
printf("main : thred %ld\n", (unsigned long)pthread_self());
while(1){
printf("main : %d\n", data);
sleep(1);
}
pthread_join(t1, (void **)&pstr);
pthread_join(t2, (void **)&pstr);
pthread_mutex_destroy(&mutex1);
return 0;
}
这个例子定义了一个全局变量data作为共享资源,要实现直到data加到3,线程1才退出。即使一开始是线程2先运行,进入循环,也最多加一次。因为sleep后线程1竞争成功会立即对互斥量加锁,直到data = 3的时候线程解锁并退出。
3.条件操作:创建,销毁,触发,广播,等待
API:
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
pthread_cond_init:第一个参数操作哪一个条件,第二个参数是属性。
int pthread_cond_destroy(pthread_cond_t *cond);
pthread_cond_destroy:参数为条件的地址
int pthread_cond_signal(pthread_cond_t *cond);
pthread_cond_signal:触发哪一个条件。
int pthread_cond_broadcast(pthread_cond_t cond);
pthread_cond_broadcast:触发所有等待这个条件的线程。
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
pthread_cond_wait:第一个参数是条件的地址,第二个参数是互斥锁的地址。
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
int data = 0;
pthread_mutex_t mutex1;
pthread_cond_t cond1;
void *func1(void *arg)
{
static int cnt = 0;
while(1){
pthread_cond_wait(&cond1, &mutex1);
printf("t1 run ///\n");
printf("t1 data is :%d\n", data);
data = 0;
sleep(1);
if(cnt ++ == 10){
printf("return 10\n");
exit(1);
}
}
}
void *func2(void *arg)
{
while(1){
printf("t2 data is :%d\n", data);
pthread_mutex_lock(&mutex1);
data++;
if(data == 3){
pthread_cond_signal(&cond1);
}
pthread_mutex_unlock(&mutex1);
sleep(1);
}
}
//
int main()
{
pthread_t t1;
pthread_t t2;
int parame = 10;
int ret;
pthread_mutex_init(&mutex1, NULL);
pthread_cond_init(&cond1, NULL);
ret = pthread_create(&t1, NULL, func1, ¶me);
if(ret == 0){
// printf("main: thread t1 create success\n");
}
ret = pthread_create(&t2, NULL, func2, ¶me);
if(ret == 0){
// printf("main: thread t2 create success\n");
}
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_mutex_destroy(&mutex1);
pthread_cond_destroy(&cond1);
return 0;
}
线程的基本操作大致就这些,可以去看一下线程生产者和消费者的相关例子进行学习。
同时也可以看一下这篇文章: