- 编译环境centos6.×64
线程创建以及结束
http://www.runoob.com/cplusplus/cpp-multithreading.html
#include <pthread.h>
pthread_create (thread, attr, start_routine, arg)
连接和分离线程
pthread_join (threadid, status)
pthread_detach (threadid)
pthread_join() 子程序阻碍调用程序,直到指定的 threadid 线程终止为止。
例子1
#include <unistd.h>
#include <pthread.h>
void* thr_fun(void* arg){
char* no = (char*)arg;
int i = 0;
for(; i < 10; i++){
printf("%s thread, i:%d\n",no,i);
if(i==5){
//线程退出(自杀)
pthread_exit(2);
//他杀pthread_cancel
}
}
return 1;
}
void main(){
//线程的引用
pthread_t tid;
pthread_create(&tid,NULL,thr_fun,"线程1");
void *rval;
pthread_join(tid,&rval);
printf("线程结束%d\n",rval);
}
代码意思,pthread_create开启了线程,当thr_fun遍历10次,当第5次的时候退出线程.
编译命令: gcc test1.c -o main -lpthread
执行 结果
[root@host threadDemo]# ./main
线程1 thread, i:0
线程1 thread, i:1
线程1 thread, i:2
线程1 thread, i:3
线程1 thread, i:4
线程1 thread, i:5
线程结束 2
例子2
多线程问题
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
int i=0;
void* thr_fun(void* arg){
char* no = (char*)arg;
for(; i < 10; i++){
printf("%s thread, i:%d\n",no,i);
sleep(1);
}
i=0;
return 1;
}
void main(){
//线程的引用
pthread_t tid,tid2;
pthread_create(&tid,NULL,thr_fun,"线程1");
pthread_create(&tid2,NULL,thr_fun,"线程2");
void *rval;
pthread_join(tid,&rval);
pthread_join(tid2,&rval);
printf("线程结束 %d",rval);
}
编译出来main2 执行后 每隔一秒先打印线程2 然后打印i
可以看出 是两个线程抢占使用thr_fun 出现这种结果 .
如果我想每个线程单独打印i ,应该怎么做 : 同步
[root@host threadDemo]# gcc 02.c -o main2 -lpthread
[root@host threadDemo]# ls
02.c main main2 test1.c thread01.c
[root@host threadDemo]# ./main2
线程2 thread, i:0
线程1 thread, i:0
线程2 thread, i:1
线程1 thread, i:2
线程2 thread, i:3
线程1 thread, i:4
线程2 thread, i:5
线程1 thread, i:6
线程2 thread, i:7
线程1 thread, i:8
线程2 thread, i:9
线程2 thread, i:1
线程2 thread, i:2
线程2 thread, i:3
线程2 thread, i:4
线程2 thread, i:5
线程2 thread, i:6
线程2 thread, i:7
线程2 thread, i:8
线程2 thread, i:9
线程结束 1
线程的同步
- 现在的目的: 第一个线程全部输出完成后,第二个线程再去打印.
int pthread_mutex_init 是一条指令,是中断指令的标识。
该函数用于C函数的多线程编程中,互斥锁的初始化。
(类似 synchronized 作用)
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
posix下抽象了一个锁类型的结构:ptread_mutex_t。通过对该结构的操作,来判断资源是否可以访问。
顾名思义,加锁(lock)后,别人就无法打开,只有当锁没有关闭(unlock)的时候才能访问资源。
即对象互斥锁的概念,来保证共享数据操作的完整性。每个对象都对应于一个可称为” 互斥锁” 的标记,
这个标记用来保证在任一时刻,只能有一个线程访问该对象。
参数一 创建一个锁
参数二指定了新建互斥锁的属性。如果参数attr为NULL,则使用默认的互斥锁属性,默认属性为快速互斥锁
- PTHREAD_MUTEX_TIMED_NP,这是缺省值,也就是普通锁。当一个线程加锁以后,其余请求锁的线程将形成一个等待队列,并在解锁后按优先级获得锁。这种锁策略保证了资源分配的公平性。
- PTHREAD_MUTEX_RECURSIVE_NP,嵌套锁,允许同一个线程对同一个锁成功获得多次,并通过多次unlock解锁。如果是不同线程请求,则在加锁线程解锁时重新竞争。
- PTHREAD_MUTEX_ERRORCHECK_NP,检错锁,如果同一个线程请求同一个锁,则返回EDEADLK,否则与PTHREAD_MUTEX_TIMED_NP类型动作相同。这样就保证当不允许多次加锁时不会出现最简单情况下的死锁。
- PTHREAD_MUTEX_ADAPTIVE_NP,适应锁,动作最简单的锁类型,仅等待解锁后重新竞争。
代码:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
int i=0;
//锁对象
pthread_mutex_t mutex;
void* thr_fun(void* arg){
char* no = (char*)arg;
//加锁的代码块
pthread_mutex_lock(&mutex);
for(; i < 10; i++){
printf("%s thread, i:%d\n",no,i);
sleep(1);
}
//取消锁
pthread_mutex_unlock(&mutex);
i=0;
return 1;
}
void main(){
//互斥锁的初始化
pthread_mutex_init(&mutex,NULL);
//线程初始化
pthread_t tid1,tid2;
pthread_create(&tid1,NULL,thr_fun,"线程1");
pthread_create(&tid2,NULL,thr_fun,"线程2");
void *rval;
pthread_join(tid1,&rval);
pthread_join(tid2,&rval);
printf("线程结束%d\n",rval);
//销毁锁
pthread_mutex_destroy(&mutex);
}
打印结果:
[root@host threadDemo]# gcc 02.c -o main2 -lpthread
02.c: In function ‘thr_fun’:
02.c:20: warning: return makes pointer from integer without a cast
[root@host threadDemo]# ls
02.c main main2 test1.c thread01.c
[root@host threadDemo]# ./main2
线程2 thread, i:0
线程2 thread, i:1
线程2 thread, i:2
线程2 thread, i:3
线程2 thread, i:4
线程2 thread, i:5
线程2 thread, i:6
线程2 thread, i:7
线程2 thread, i:8
线程2 thread, i:9
线程1 thread, i:0
线程1 thread, i:1
线程1 thread, i:2
线程1 thread, i:3
线程1 thread, i:4
线程1 thread, i:5
线程1 thread, i:6
线程1 thread, i:7
线程1 thread, i:8
线程1 thread, i:9
线程结束1
可以看到 先打印了线程二执行的输入 结束之后才打印线程一的输出.
生产者消费者
阻塞在条件变量上pthread_cond_wait
解除在条件变量上的阻塞pthread_cond_signal
https://blog.csdn.net/ffilman/article/details/4871920
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
//模拟 产品队列
int ready = 0;
//互斥锁
pthread_mutex_t mutex;
//条件变量 判断是否有产品
pthread_cond_t has_product;
//生产者
void* produce(void *arg){
char* name = (char*)arg;
for(;;) {
//锁住
pthread_mutex_lock(&mutex);
ready++;//生产进入队列
printf("%s 生产 %d \n",name,ready);
//发送一条解锁消息
pthread_cond_signal(&has_product);
//解锁
pthread_mutex_unlock(&mutex);
sleep(3);
}
}
//消费者
void* consumer(void* arg){
char* name = (char*)arg;
for(;;){
//加锁
pthread_mutex_lock(&mutex);
//如果产品列表为空 继续等待, 因为有可能不止一个消费者
while(ready==0){
printf("没有产品了,等待生产\n");
//等待
pthread_cond_wait(&has_product,&mutex);
}
//消费 出队列
printf("%s 消费%d\n",name,ready);
ready--;
printf(" 当前产品%d\n",ready);
//解锁
pthread_mutex_unlock(&mutex);
sleep(1);
}
}
void main(){
//互斥锁初始化
pthread_mutex_init(&mutex,NULL);
//条件变量初始化
pthread_cond_init(&has_product,NULL);
//线程的引用 这里三个 一个生产两个消费
pthread_t tid1,tid2,tid3;
pthread_create(&tid1,NULL,produce,"生产者1");
pthread_create(&tid2,NULL,consumer,"消费者1");
pthread_create(&tid3,NULL,consumer,"消费者2");
printf("开启线程");
void *rval;
pthread_join(tid1,&rval);
pthread_join(tid2,&rval);
pthread_join(tid3,&rval);
printf("线程结束%d\n",rval);
}
结果:
开启线程没有产品了,等待生产
没有产品了,等待生产
生产者1 生产 1
消费者2 消费1
当前产品0
没有产品了,等待生产
生产者1 生产 1
消费者1 消费1
当前产品0
没有产品了,等待生产
生产者1 生产 1
消费者2 消费1
当前产品0
没有产品了,等待生产
生产者1 生产 1
消费者1 消费1
当前产品0
没有产品了,等待生产
生产者1 生产 1
消费者2 消费1
当前产品0
没有产品了,等待生产
生产者1 生产 1
消费者1 消费1
当前产品0
没有产品了,等待生产
生产者消费者模式.