原创:http://blog.sina.com.cn/u/2312748742
linux 线程
一、线程的创建:
1) int pthread_create(pthread_t *thread,pthread_attr_t *attr,
void*(*start_routine)(void*),void *arg)
2)thread:新线程创建成功后,保存新线程的标识符。
3)attr:设置线程的属性,可用NULL.
4)start_routine:函数的地址。回调函数。
5)arg:传给线程启动参数的参数。
二、结束回调函数:
1)void pthread_exit(void *retbal);
返回一个指向某个对象的指针。不能返回一个指向局部变量的指针
三、线程结束后归并到一起。
1)int pthread_join(pthread_t th,void **thread_return);
2)th 指定将要等待的线程标识符。
3)thread_return:指向另一个指针。后者指向线程返回值。
4)pthread_join相当于进程用来等待子进程的wait函数。
四、编译时用g++ -o pthread pthread.cpp -lpthread (-lpthread为链接到动态库中)
例子:非绑定,要手动清除
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#define ERR_EXIT(m) do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
void* pthread_start(void*)
{
printf("hello world\n");
sleep(1);
pthread_exit((void *)"pthread over\n");
}
int main()
{
pthread_t threadId=0;
//pthread_attr_t attr;
//pthread_attr_init(&attr); //初始化属性
//pthread_attr_setscope(&attr,PTHREAD_SCOPE_SYSTEM);//绑定
//pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);//分离
int rlt= pthread_create(&threadId,NULL,pthread_start,NULL);
if(rlt!=0)
{
ERR_EXIT("pthread_create error");
}
void *thread_return;
rlt=pthread_join(threadId, &thread_return); //回调函数的返回值
printf("%s",thread_return);
}
绑定,设置自动分离
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#define ERR_EXIT(m) do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
void* pthread_start(void*)
{
printf("hello world\n");
sleep(1);
pthread_exit((void *)"pthread over\n");
}
int main()
{
pthread_t threadId=0;
pthread_attr_t attr;
pthread_attr_init(&attr); //初始化属性
pthread_attr_setscope(&attr,PTHREAD_SCOPE_SYSTEM);//绑定
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);//分离
int rlt= pthread_create(&threadId,NULL,pthread_start,NULL);
if(rlt!=0)
{
ERR_EXIT("pthread_create error");
}
while(1)
{
sleep(5);
break;
}
printf("main exit\n");
}
五、线程间的同步
用信号量:
int sem_init(sem_t *sem,int pshared,unsigned value);
1)sem 要进行初始化的信号量对象。
2)pshared 控制着信号量的类型 0:线程间。非0:进程间
3)value 赋给信号量对象的一个整数类型的初始值。
4)调用成功返回0
六、p操作,减1操作
int sem_wait(sem_t *sem);
七、V操作,加1操作
int sem_post(sem_t *sem);
八、用完信号量后,要对信号量进行清理
int sem_destroy(sem_t *sem);
例子:
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#define ERR_EXIT(m) do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
int glb_Max = 10; //要设为全局变量
//同步信号量 生产数量
sem_t semPruc;
//同步信号量 可消费数量
sem_t semConsum;
void* pthread_produce(void*)
{
int max = 10;
while(true)
{
//还可以生产几个
sem_wait(&semPruc); //生产信号量-1
printf("pthread_produce: produce one..\n");
//writeLog()
sleep(1);
sem_post(&semConsum); //消费信号量+1
max--;
if(max <=0)
{
break;
}
}
pthread_exit((void *)"pthread_produce over");
}
void* pthread_consume(void*)
{
int max = 10;
while(true)
{
//还可以生产几个
sem_wait(&semConsum); //消费信号量-1
printf("pthread_consume: consume one..\n");
sleep(3);
sem_post(&semPruc); //生产信号量+1
max--;
if(max <=0)
{
break;
}
}
pthread_exit((void *)"pthread_consume over");
}
void writeLog(char *info)
{
//互斥锁
//
}
int main()
{
pthread_t threadConId = 0;
pthread_t threadProId = 0;
//信号量初始化
int rlt = sem_init(&semPruc,0,6);//最多允许生产6个 6个资源数
rlt = sem_init(&semConsum, 0, 0);
//消费
rlt = pthread_create(&threadConId, NULL, pthread_consume, NULL);
if( rlt !=0 )
{
ERR_EXIT("pthread_create error...\n");
}
//生产
rlt = pthread_create(&threadProId, NULL, pthread_produce, NULL);
if( rlt !=0 )
{
ERR_EXIT("pthread_create error...\n");
}
sem_destroy(&semConsum); //销毁信号量
sem_destroy(&semPruc);
pthread_join(threadConId, NULL); //等待信号量没有这个的话就会强制结束线程
pthread_join(threadProId, NULL);
}
--------------------------------------------------------------------------
互斥锁机制,保护关键代码段:
例子:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
void * thread_func(void *arg);
pthread_mutex_t work_mutex;//=PTHREAD_MUTEX_INITIALIZER;//初始化
int g_num = 0;
int main() {
int res;
pthread_t a_thread;
void *thread_result;
res = pthread_mutex_init(&work_mutex,NULL);
res = pthread_create(&a_thread,NULL,thread_func,NULL);
sleep(2);
pthread_mutex_lock(&work_mutex);
g_num ++;
printf("Waiting for thread to joined \n");
pthread_mutex_unlock(&work_mutex);
res = pthread_join(a_thread,&thread_result);
printf("thread joined\n");
exit(0);
}
void* thread_func(void *arg)
{
printf("Sub Thread running now.\n");
pthread_mutex_lock(&work_mutex);
sleep(4);
printf("g_num in subThread is %d\n",g_num);
pthread_mutex_unlock(&work_mutex);
pthread_exit(0);
}
执行后显示:
Sub Thread running now
g_num in subThread is 0
Waiting for thread to joined
thread joined
---------------------------------------------------------
防止死锁方法:
1)设置超时线程,定期检查
2)pthread_cleanup_push();和pthread_cleanup_pop()//可以看成是{ } 当跳出时就会unlock
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
void * thread_func(void *arg);
pthread_mutex_t work_mutex;//=PTHREAD_MUTEX_INITIALIZER;//初始化
int g_num = 0;
int main() {
int res;
pthread_t a_thread;
void *thread_result;
res = pthread_mutex_init(&work_mutex,NULL);
res = pthread_create(&a_thread,NULL,thread_func,NULL);
sleep(2);
pthread_mutex_lock(&work_mutex);
g_num ++;
printf("Waiting for thread to joined \n");
pthread_mutex_unlock(&work_mutex);
res = pthread_join(a_thread,&thread_result);
printf("thread joined\n");
exit(0);
}
void* thread_func(void *arg)
{
printf("Sub Thread running now.\n");
pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, &work_mutex); //{
pthread_mutex_lock(&work_mutex);
sleep(4);
printf("g_num in subThread is %d\n",g_num);
pthread_exit(0);
pthread_mutex_unlock(&work_mutex);
pthread_cleanup_pop(0);//} //只要跳出花括号就会进行解锁 如果有两个就在写一遍,变成2 { {} }
pthread_exit(0);
}