/* 2.4GNU/Linux内核的POSIX线程库基于Linux进程实现(于1996年问世),在GNU/Linux进程模型的基础上构建的。 2.6内核使用了新的本地POSIX线程库,或称为NPTL(于2002年引入),比旧库有了很多改进,执行效率更高。 要想知道正在使用的是那个P(POSIX)线程库,可以使用如下命令: getconf GNU_LIBPTHREAD_VERSION 自己使用的为:NPTL 2.13.90 线程和进程的区别: 创建进程并进行实际写内存的时候,会为进程分配完整的内存空间,包括text段、data段和内存栈; 创建线程的时候,只是为线程分配一个新的私有的线程栈和一个独有的上下文环境(程序计数器PC和存储寄存器等),其余的部分与父进程共用。 线程分享数据,如打开的文件描述符和套接字。要防止数据共享造成的冲突。 编译线程程序时要添加'-pthread -lpthread'参数 gcc -pthread -Wall test.c -o test -lpthread */ /* 用pthread_create创建一个线程 */ #include <pthread.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <unistd.h> void* myThread( void* arg ) { pthread_t pt; pt=pthread_self( ); printf( "Thread %x ran/n",( int )pt ); //terminate the thread pthread_exit( arg ); } int main( ) { int ret,status; pthread_t mythread; ret=pthread_create( &mythread,NULL,myThread,NULL ); if( ret!=0 ) { printf( "CANT CREATE pthread ( %s )/n",strerror( errno ) ); exit( -1 ); } //pthread_join就像进程中的wait函数,如果没有pthread_join,则可能 //看不到线程的输出 pthread_join( mythread,&status ); return 0; } /* 线程的同步:让线程的创建者等待这个线程结束。由pthread_join()函数完成 使用pthread_join加入线程 */ #include <pthread.h> #include <stdio.h> void* myThread( void* arg ) { printf( "Thread %d started/n",( int )arg ); pthread_exit( arg ); } #define MAX_THREADS 5 int main( ) { int ret,i,status; pthread_t threadIds[ MAX_THREADS ]; for( i=0;i<MAX_THREADS;++i ) { ret=pthread_create( &threadIds[ i ],NULL,myThread,( void* )i ); if( ret!=0 ) printf( "Error creating thread %d/n",i ); } /* for( i=0;i<MAX_THREADS;++i ) { ret=pthread_join( threadIds[ i ],( void** )&status ); if( ret!=0 ) printf( "Error joining thread %d/n",i ); else printf( "Status=%d/n",status ); } */ return 0; } /* 结果对于每次的运行都不一样,有的线程创建成功,有的创建不成功: winlin@localhost threadProgram$ ./test Thread 0 started Thread 4 started Thread 3 started winlin@localhost threadProgram$ ./test Thread 0 started Thread 2 started Thread 1 started Thread 4 started Thread 3 started 如果不注释掉pthread_join的for循环结果如下: Thread 0 started Thread 1 started Thread 3 started Thread 4 started Thread 2 started Status=0 Status=1 Status=2 Status=3 Status=4 winlin@localhost threadProgram$ ./test Thread 0 started Thread 3 started Thread 4 started Thread 1 started Thread 2 started Status=0 Status=1 Status=2 Status=3 Status=4 从Status的顺序可知,pthread_join确实可以同步线程 */ /* 互斥是保证一个线程在关键区正常执行的变量。 关键区是同一时间只允许一个进程来执行的代码段。关键区的存在是为了保护共享资源,避免多重访问的发生。 简单实例: pthread_mutex_t cntr_mutex=PTHREAD_MUTEX_INITIALIZER; assert( pthread_mutex_lock(&cntr_mutex)==0 ); //Critical Section assert( pthread_mutex_unlock(&cntr_mutex)==0 ); */ /* 利用互斥保护关键区的变量 */ #include <pthread.h> #include <assert.h> #include <stdio.h> pthread_mutex_t cntr_mutex=PTHREAD_MUTEX_INITIALIZER; long protVariable=0L; void* myThread( void* arg ) { int i,ret; for( i=0;i<4;++i ) { ret=pthread_mutex_lock( &cntr_mutex ); assert( ret==0 ); printf( "thread %d perform the protVariable/n",( int )arg ); ++protVariable; assert( pthread_mutex_unlock(&cntr_mutex)==0 ); } pthread_exit( NULL ); } #define MAX_THREADS 3 int main( ) { int i; pthread_t threadIds[ MAX_THREADS ]; for( i=0;i<MAX_THREADS;++i ) { if(pthread_create(&threadIds[ i ],NULL,myThread,( int* )i) ) printf("Error creating thread %d/n",( int )threadIds[ i ]); } for( i=0;i<MAX_THREADS;++i ) { if( pthread_join( threadIds[ i ],NULL ) ) printf("Error joining thread %d/n",( int )threadIds[ i ]); } printf( "The protected variable value is %ld/n",protVariable ); if( pthread_mutex_destroy( &cntr_mutex ) ) printf( "Coundn't destroy the mutex/n" ); return 0; } /* 结果: thread 0 perform the protVariable thread 0 perform the protVariable thread 0 perform the protVariable thread 0 perform the protVariable thread 2 perform the protVariable thread 2 perform the protVariable thread 2 perform the protVariable thread 2 perform the protVariable thread 1 perform the protVariable thread 1 perform the protVariable thread 1 perform the protVariable thread 1 perform the protVariable The protected variable value is 12 */ //如果把线程函数改为如下: //经过实验,当线程数和循环数较大时,将会导致结果不确定 void* myThread( void* arg ) { int i,ret; for( i=0;i<10;++i ) { //ret=pthread_mutex_lock( &cntr_mutex ); //assert( ret==0 ); printf( "thread %d perform the protVariable/n",( int )arg ); ++protVariable; // assert( pthread_mutex_unlock(&cntr_mutex)==0 ); } pthread_exit( NULL ); } /*注意: 在使用互斥的时候,只把确实需要放入关键区的工作放入关键区,保证关键区最小化是十分重要的。因为 互斥会阻断其他线程,最小化关键区执行的时间可以提升程序性能 */