Linux多线程实践(2) --线程基本API
2015-02-19 16:33
330 查看
POSIX线程库
与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都是以“pthread_”开头,要使用这些函数库,要通过引入头文<pthread.h>,而且链接这些线程函数库时要使用编译器命令的“-lpthread”选项[Ubuntu系列系统需要添加的是”-pthread”选项而不是”-lpthread”,如Ubuntu 14.04版本,深度Ubuntu等]1.pthread_create
int pthread_create(pthread_t *restrict thread,
const pthread_attr_t *restrict attr,
void *(*start_routine)(void*), void *restrict arg);创建一个新的线程
参数
thread:线程ID
attr:设置线程的属性,一般设置为NULL表示使用默认属性
start_routine:是个函数地址,线程启动后要执行的函数
arg:传给线程启动函数的参数
返回值:成功返回0;失败返回错误码;
附-Posix错误检查
UNIX传统的函数:成功返回0,失败返回-1,并且对设置全局变量errno以指定错误类型。然而pthreads函数出错时不会设置全局变量errno(而其他的大部分POSIX函数会设置errno)。而是将错误代码通过返回值返回;
pthreads同样也提供了线程内的errno变量,对于每一个线程, 都有一个errno的值, 以支持其它使用errno的代码。对于pthreads函数的错误,建议通过返回值进行判定,因为读取返回值要比读取线程内的errno变量的开销更小!/** 实践: 新的错误检查与错误退出函数 **/
inline void err_check(const std::string &msg, int retno)
{
if (retno != 0)
err_exit(msg, retno);
}
inline void err_exit(const std::string &msg, int retno)
{
std::cerr << msg << ": " << strerror(retno) << endl;
exit(EXIT_FAILURE);
}2.pthread_exitvoid pthread_exit(void *value_ptr);线程终止
value_ptr:指向该线程的返回值;注意:value_ptr不能指向一个局部变量。
3.pthread_joinint pthread_join(pthread_t thread, void **value_ptr);等待线程结束
value_ptr:它指向一个指针,后者指向线程的返回值(用户获取线程的返回值)/** 示例: 等待线程退出 **/
void *thread_rotine(void *args)
{
for (int i = 0; i < 10; ++i)
{
printf("B");
fflush(stdout);
usleep(20);
}
pthread_exit(NULL);
}
int main()
{
pthread_t thread;
int ret = pthread_create(&thread, NULL, thread_rotine, NULL);
err_check("pthread_create", ret);
for (int i = 0; i < 10; ++i)
{
printf("A");
fflush(stdout);
usleep(20);
}
ret = pthread_join(thread, NULL);
err_check("pthread_join", ret);
putchar('\n');
return 0;
}4.pthread_selfpthread_t pthread_self(void);返回线程ID/** 示例:主控线程与子线程传递数据 **/
typedef struct _Student
{
char name[20];
unsigned int age;
} Student;
void *threadFunction(void *args)
{
cout << "In Thread: " << pthread_self() << endl;
Student tmp = *(Student *)(args);
cout << "Name: " << tmp.name << endl;
cout << "Age: " << tmp.age << endl;
pthread_exit(NULL);
}
int main()
{
Student student = {"xiaofang",22};
pthread_t thread;
//启动创建并启动线程
pthread_create(&thread,NULL,threadFunction,&student);
//等待线程结束
pthread_join(thread,NULL);
return 0;
}
5.pthread_cancelint pthread_cancel(pthread_t thread);取消一个执行中的线程
6.pthread_detachint pthread_detach(pthread_t thread); 将一个线程分离-如果在新创建的线程结束时主线程没有结束同时也没有调用pthread_join,则会产生僵线程,次问题可以通过设置线程为分离的(detach)来解决;
总结:进程 VS. 线程
进程(pid_t) | 线程(pthread_t) |
Fork | Pthread_create |
Waitpit | Pthread_join/Pthread_detach |
Kill | Pthread_cancel |
Pid | Pthead_self |
Exit/return | Pthread_exit/return |
僵尸进程(没有调用wait/waitpid等函数) | 僵尸线程(没有调用pthread_join/pthread_detach) |
/** 将并发echo server改造成多线程形式 注意线程竞速问题的解决 **/ void echo_server(int clientSocket); void *thread_routine(void *arg); int main() { int sockfd = socket(AF_INET,SOCK_STREAM,0); if (sockfd == -1) err_exit("socket error"); int optval = 1; if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval)) == -1) err_exit("setsockopt error"); struct sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(8002); serverAddr.sin_addr.s_addr = INADDR_ANY; //绑定本机的任意一个IP地址 if (bind(sockfd,(struct sockaddr *)&serverAddr,sizeof(serverAddr)) == -1) err_exit("bind error"); if (listen(sockfd,SOMAXCONN) == -1) err_exit("listen error"); while (true) { int peerSockfd = accept(sockfd, NULL, NULL); if (peerSockfd == -1) err_exit("accept error"); pthread_t tid; /**注意: 下面这种用法可能会产生"竞速问题" 当另一个连接快读快速到达, peerSockfd的内容更改, 新创建的线程尚未将该值取走时,线程读取的就不是 我们想让线程读取的值了 int ret = pthread_create(&tid, NULL, thread_routine, (void *)&peerSockfd); **/ //解决方案: 为每一个链接创建一块内存 int *p = new int(peerSockfd); int ret = pthread_create(&tid, NULL, thread_routine, p); if (ret != 0) err_thread("pthread_create error", ret); } close(sockfd); }
void *thread_routine(void *args) { //将线程设置分离状态, 避免出现僵尸线程 pthread_detach(pthread_self()); int peerSockfd = *(int *)args; //将值取到之后就将这块内存释放掉 delete (int *)args; echo_server(peerSockfd); cout << "thread " << pthread_self() << " exiting ..." << endl; pthread_exit(NULL); } void echo_server(int clientSocket) { char buf[BUFSIZ] = {0}; int readBytes; while ((readBytes = read(clientSocket, buf, sizeof(buf))) >= 0) { if (readBytes == 0) { cerr << "client connect closed" << endl; break; } if (write(clientSocket, buf, readBytes) == -1) { cerr << "server thread write error" << endl; break; } cout << buf; bzero(buf, sizeof(buf)); } }其完整源代码:download.csdn.net/detail/hanqing280441589/8440763
相关文章推荐
- Linux多线程实践(2) --线程基本API
- Linux多线程实践(三)线程的基本属性设置API
- Linux多线程实践(2) --线程基本API
- Linux多线程实践(2) --线程基本API
- Linux多线程实践(2) --线程基本API
- Linux多线程实践(三)线程的基本属性设置API
- Linux多线程实践(2) --线程基本API
- Linux多线程实践(三)线程的基本属性设置API
- Linux多线程实践(三)线程的基本属性设置API
- Linux多线程实践(一)线程基本概念和理论
- Linux多线程实践(二)线程基本API(POSIX)
- Linux多线程实践(3) --线程属性
- Linux下的socket编程实践(二)socket编程基本API简介
- Linux多线程实践(4) --线程特定数据
- Linux多线程实践(1) --线程理论
- Java并发编程实践之线程的基本控制
- java的线程的基本知识点和API
- Linux多线程实践(1) --线程理论
- Linux多线程实践(1) --线程理论
- Linux多线程实践(四 )线程的特定数据