线程概述
为什么使用线程
- 并行parallelism的需要
- 避免程序因为低速的IO操作阻塞
- 尽管可以用多进程解决一些问题,但是线程可以共享一个内存地址空间,当需要贡献数据的时候线程的选择更自然
线程的问题
- 共享数据比较难操作
- 不可控制的执行计划
- 线程等待其他线程
线程Thread API
1.Thread Creation
#include <pthread.h>
int
pthread_create( pthread_t * thread,
const pthread_attr_t * attr,
void * (*start_routine)(void*),
void * arg);
第一个参数 thread 是结构类型pthread_t 的指针,我们用它来和thread交互,所以需要把它传给pthread_create()来初始化它
第二个参数是是设置线程的属性
第三个线程要执行的function
第四个是第三个参数function的参数
代码
#include <pthread.h> 2
typedef struct __myarg_t {
int a;
int b;
} myarg_t;
void *mythread(void *arg) {
myarg_t *m = (myarg_t *) arg;
printf("%d %d\n", m->a, m->b);
return NULL;
}
int
main(int argc, char *argv[]) {
pthread_t p;
int rc;
myarg_t args;
args.a = 10;
args.b = 20;
rc = pthread_create(&p, NULL, mythread, &args);
//...
}
2.Thread Completion
typedef struct __myret_t {
int x;
int y;
} myret_t;
void *mythread(void *arg) {
myarg_t *m = (myarg_t *) arg;
printf("%d %d\n", m->a, m->b);
myret_t *r = malloc(sizeof(myret_t));
r->x = 1;
r->y = 2;
return (void *) r;
}
pthread_t p; //线程
myret_t *m; //线程返回结果
pthread_create(&p, NULL, mythread, &args);
pthread_join(p, (void **) &m);
3.Locks
POSIX线程库除了线程的创建和完成另一个最常用的函数系列就是locks 了
pthread_mutex_t lock; //声明一个锁
pthread_mutex_lock(&lock); //获得锁
x = x + 1; // 你认为的重要的业务代码部分
pthread_mutex_unlock(&lock);//释放锁
4.Condition Variables
POSIX线程库另外一个重要的部分就是condition variables **pthread_cond_t **
当多个线程之间需要交流信号的时候condition variables就非常有用
//让调用的线程sleep 等待其他线程唤醒(signal)它
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
//唤醒(signal)操作
int pthread_cond_signal(pthread_cond_t *cond);
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
Pthread_mutex_lock(&lock);
//当ready==0的时候sleep
while (ready == 0)//ready 全局的变量
Pthread_cond_wait(&cond, &lock);
Pthread_mutex_unlock(&lock);
pthread_mutex_lock(&lock);
//ready 等于1了,唤醒上面那个sleep的线程
ready = 1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);