本文为自己的懒人笔记,没怎么梳理。看到什么小点,就写了什么小点。
懒人笔记
1.进程空间:
text:只读,包括常量
data: stack heap static
bss:未初始化的全部变量,静态变量2.线程的特点是只具有自己的堆栈区
其他空间全部共享,所以,线程并不是没有自己空间的,如果堆栈的变量想要传递就没法直接共享。3.主线程一旦退出,进程结束。
所以,多线程的时候,如果主线程退出,那么进程空间回收。其他线程歇菜。
线程的特点还是开销比较小。4.线程有三种退出方式:
线程可以简单的从启动例程中返回,返回值是线程的退出码。
线程可以被同一进程中的其他线程取消。
线程调用pthread_exit();5.pthread_self()获取线程id.
注意返回值是 unsigned long int,所以打印的时候要使用%lu方式。
为什么线程退出:一定是pthread_exit或者是简单退出,不能是exit
因为后者是进程退出,只要线程调用该函数,进程空间回收,所有资源都没有了。6.进程退出注意两个点:
1.不能用exit退出,这是退出进程。整个线程都将被销毁
2.资源要回收。7.说起资源回收,也是和进程的不同。
进程的资源回收必须是父进程,但是线程可以主线程回收,也可以系统去回收。
线程有两种状态,joinable and detatch8.这一对好朋友需要说一下:
void pthread_exit(void* retval);
void pthread_join( pthread_t thread, void** retval );
一个返回,一个接受。到底什么关系。
先说pthread_exit, 粘一段手册的内容:
The value pointed to by retval should not be located on the calling thread’s stack, since the contents of that stack are undefined after the thread terminates.
也就是说,retval其实是返回值的地址,是一个传出参数。
再说pthread_join,主要是弄清楚,为什么是void**类型。因为对于pthread_exit的传出参数retval来说,pthread_join其实获取的是这个值,但是如果在主线程当中想要获取这个值,那只能把这个值传出去。因此,需要一个传出参数。那就只能是retval这个变量的地址,因此是type(&retval)类型,即void* 类型.9.calloc需要初始化,malloc则不需要初始化。
10.int pthread_cancle( pthread_t thread );对于这个函数而言,也是线程退出的一种方式。先初步了解,手册是这么说的:send a cancellation request to a thread.注意,只是send a caccellation request,thread不是立即退出。它必须得到cancellation point才可以退出终止。
一般而言根据POSIX标准,pthread_join()、pthread_testcancel()、pthread_cond_wait()、pthread_cond_timedwait()、sem_wait()、sigwait()等函数以及read()、write()等会引起阻塞的系统调用都是Cancelation-point,而其他pthread函数都不会引起Cancelation动作。11.说一个用它的场景:
考虑这样一个问题。
现在有10000个人,每个人的名字都不一样。
我现在需要找到 kang这个人,假设这个人一定存在的。
那么怎么找?
第一种办法:枚举,当然不好。因为量很大。
其次,多线程。
thd1: 1-1000
thd2; 1001 - 2000
….thd10 - 9000-10000
假设现在这个人的编号是1234,那么第二个想成找到之后返回,其他线程没有必要找了。
主线程可以把其他线程杀死。12.线程终止清理函数,主要是在线程异常终止,还没回收资源,就被释放了。
所以,资源没有回收,利用清理函数。13.线程最麻烦的是,如果有一个线程异常退出了,那么整个进程都会退出。这会导致其他线程也异常退出,整个系统挂掉。
但是,多进程就不会出现这个问题。14.注意一点,pthread_create失败返回非0,不是-1.小心
15.对共享变量的访问,没有办法是原子操作,导致操作异常。
try_lock()加锁不成功时,不会阻塞。通过返回值判断一下。
锁的初始化有静态和动态两种形式。
一般使用动态。16.
void* thread_handle( void* arg ){
printf( “thread: %lu\n”, pthread_self() );
int* pcnt = (int*)arg;
int cnt = *pcnt;
while(cnt–){
++g_val;
}
printf( “hello,world” ); // 这里这么写也是 不行的!!!
pthread_exit(NULL);
}
因为本质上他们都访问了stdout这个文件,相当于读者-写者问题。不行。
代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void err_handle(const char* msg){
perror(msg);
exit(1);
}
void* thread_handle( void* arg ){
char* msg = (char*)arg;
printf( "thread: %s\n", msg );
printf( "thread id: %lu\n", pthread_self() );
int fds[2];
pipe(fds);
char buf[1024];
read( fds[0], buf, 1023 );
/*
char* ret_msg = "how are you!\n";
pthread_exit((void*)ret_msg); // return
*/
/*
int* ret_val = (int*)malloc( sizeof(int) * 1 );
*ret_val = 1024;
if(!ret_val){
err_handle("malloc");
}
pthread_exit( (int*)ret_val );
*/
pthread_exit(NULL);
}
int main( int argc, char* argv[] ){
pthread_t tid;
int ret = 0;
char* s = "hello,world!";
printf( "main id: %lu\n", pthread_self() );
ret = pthread_create( &tid, NULL, thread_handle, (void*)s );
if(-1 == ret){
err_handle("pthread_create");
}
/*这个是通常情况下退出,不需要线程的返回参数。
ret = pthread_join(tid, NULL);
if(-1 == ret){
err_handle("pthread_join");
}
printf( "Thread join!\n" );
*/
/*
char* ret_msg = NULL;
ret = pthread_join(tid, (void**)&ret_msg);
if(-1 == ret){
err_handle("pthread_join");
}
printf("thread has finished, retval is %s\n", ret_msg);
exit(EXIT_SUCCESS);
*/
/*
int* ret_val = NULL;
ret = pthread_join( tid, (void**)&ret_val );
if(-1==ret){
err_handle("pthread_join");
}
printf( "thread join: ret_val is %d\n", *ret_val );
*/
pthread_cancel(tid);
exit(EXIT_SUCCESS);
}
代码
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define N 2 // thread num
void err_handle(const char* msg){
perror(msg);
exit(EXIT_FAILURE);
}
void* thread_handle(void* arg);
int g_val = 0; // global variable
typedef struct task{
int cnt;
pthread_mutex_t* pmylock;
}task_t,*ptask;
int main( int argc, char* argv[] ){
pthread_t tid_arr[N];
int i = 0;
int ret = 0;
int cnt = 100000000;
pthread_mutex_t mylock;
ret = pthread_mutex_init(&mylock, NULL);
if(ret){
err_handle("pthread_mutex_init");
exit(EXIT_FAILURE);
}
task_t a_task;
a_task.cnt = cnt;
a_task.pmylock = &mylock;
for(i = 0; i < N; ++i){
ret = pthread_create( tid_arr + i, NULL, thread_handle, (void*)&a_task );
if(0 != ret) err_handle("pthread_create");
}
for(i = 0; i < N; ++i){
ret = pthread_join(tid_arr[i], NULL);
if(-1 == ret) err_handle("pthread_join");
}
ret = pthread_mutex_destroy(&mylock);
if(ret){
err_handle("pthread_mutex_destroy");
exit(EXIT_FAILURE);
}
printf( "main: %lu\n", pthread_self() );
printf("g_val = %d\n", g_val);
exit(EXIT_SUCCESS);
}
void* thread_handle(void* arg){
ptask p_a_task = (ptask)arg;
int cnt = p_a_task->cnt;
int i;
pthread_mutex_lock(p_a_task->pmylock);
for(i = 0; i < cnt; ++i){
++g_val;
}
pthread_mutex_unlock(p_a_task->pmylock);
printf("thread: %lu\n", pthread_self());
pthread_exit(NULL);
}
代码
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <malloc.h>
#include <errno.h>
void err_msg( int en , const char* msg );
void err_msg1( const char* msg );
void err_msg2( const char* msg );
void* thread_handle( void* );
int main( int argc, char* argv[] ){
pthread_t tid = 0;
int ret = 0;
int i = 0;
int ret_val = 0; // 返回值这里,线程返回什么类型,这里写什么类型即可。其实应该写int* ret_val;但是线程返回值不是指针类型,它是直接把值类型,强转。因为,指针变量和整型变量都是占4个字节,所以虽然这么转不是非常纯正,但是并不会出错。语义不好,但是可以实现。
ret = pthread_create(&tid, NULL, thread_handle, NULL );
if( 0 != ret ){
err_msg(ret, "pthread_create");
}
for( i = 0; i < 10; ++i ){
printf( "%lu : hello my child!\n", pthread_self() );
if(5==i)
pthread_cancle(tid);
sleep(1);
}
ret = pthread_join(tid, (void**)&ret_val);
if( 0 != ret ){
err_msg(ret, "pthread_join");
}
printf( "%lu: Thread is joined, retval is %d\n", pthread_self(), ret_val );
exit(EXIT_SUCCESS);
}
void err_msg( int en, const char* msg ){
errno = en;
perror(msg);
exit(EXIT_FAILURE);
}
void err_msg1( const char* msg ){
perror(msg);
exit(EXIT_FAILURE);
}
void err_msg2( const char* msg ){
fprintf(stderr, "%s\n", msg );
exit(EXIT_FAILURE);
}
void* thread_handle( void* arg){
int i = 0;
char* msg = (char*)malloc( sizeof(char) * 32 );
if(!msg)
err_msg2("Not enough space!");
for( i = 0; i < 10; ++i ){
printf( "%lu: Hello, my father!\n", pthread_self() );
sleep(1);
}
free(msg);
printf("Dynamic space is freed!\n");
pthread_exit((void*)10);
}
代码
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <malloc.h>
#include <errno.h>
void err_msg( int en , const char* msg );
void err_msg1( const char* msg );
void err_msg2( const char* msg );
void* thread_handle( void* );
int main( int argc, char* arg