注意:与进程区分开来。
线程同步:多个线程按照先后顺序执行,就像是排了队列一样,一个一个来;
线程互斥:多个线程对同个资源操作,为了保证被访问资源的原子性(一次只能有一个线程使用资源),所以要互斥。
一、什么是多线程
* 线程就是“轻量级”的进程。
* 线程与创建它的进程共享代码段,数据段。
* 线程拥有自己独立的栈
二、多线程函数
(转)所谓最简单的多线程编程,就是通过pthread_create,pthread_join,pthread_exit 3个api实现线程的创建与终止,而创建的线程只做些简单的工作,如printf一些文字信息。
使用pthread_create,pthread_join,pthread_exit 进行多线程编程的模型如下图所示:
- pthread_create
//原型:int pthread_create(pthread_t * thread, const pthread_attr_t * attr, void * (*start_routine)(void *), void *arg)
/*
* @function :按照给定的线程属性attr,在一个进程(process)里创建一个新的线程(thread)
* @param attr:
* 如果attr为NULL,则内部使用默认的属性创建线程。如果在创建线程之后修改attr,则不会对已经创建的线程产生作用。
* @param thread:
* 创建线程成功后,将thread id存储在thread里,返回给调用者。否则thrad的值是未定义的。
* @param start_routine:
* 线程创建成功后,开始执行线程的入口函数start_routine。
* @param arg:
* 调用者通过arg指定线程入口函数start_routine专用的参数指针。
* @return :
* 0 创建成功返回0
* EAGAIN 超出了系统限制,如创建的线程太多,一个进程最多创建线程个数PTHREAD_THREADS_MAX。
* EINVAL attr 的值无效
* @note pthread_create创建线程后,线程入口函数即开始执行,不需要显示控制start_routine开始执行。
* 如果确实需要将此过程分为create和start2步来控制start_routine稍后执行,
* start_routine可以通过等待一个条件变量(condition variable)进行同步的方式实现。
* Compile and link with -pthread.例如:gcc -lphread
*/
- pthread_exit
/**
- @function void pthread_exit(void *status)
- 终止调用者线程,
- @param status:
- 通过status设置退出状态,与pthread_join配对使用
- @return :
- 无返回值,也不返回到其调用方。
- @note
- 如果调用线程尚未分离,则线程ID 和status 指定的退出状态将保持不变,直到应用程序调用pthread_join() 以等待该线程。
- 否则,将忽略status。线程ID 可以立即回收。
*/
- pthread_join
/**
- @function int pthread_join(pthread_t thread, void **status);
- 等待thread线程终止
- 如果thread指代的线程还没有终止,将导致调用线程挂起,直到thread指代的线程终止为止。
- @param thread:
- 所等待的的终止线程
- @param status:
- 如果status的值不等于NULL,那么它的值是通过pthread_exit传递过来的。
- @return :
- 0 线程已经终止
- ESRCH 多个线程不能等待同一个线程完成,否则仅有一个线程会成功完成。其他线程将终止,并返回ESRCH 错误。
- EINVAL 一般表示thread是无效的参数
- EDEADLK 检查到死锁状态
- @note
- 如果调用线程尚未分离,则线程ID 和status 指定的退出状态将保持不变,直到应用程序调用pthread_join() 以等待该线程。
- 否则,将忽略status。线程ID 可以立即回收。
*/
三、多线程互斥:
1. 线程的互斥函数有:
1. 互斥函数的初始化:pthread_mutex_init();
2. 互斥函数的锁定函数pthread_mutex_lock();
3. 互斥函数的解锁函数pthread_mutex_unlock();
4. 互斥函数的销毁函数pthread_mutex_destroy()。
四、多线程同步:
1. 初始化
* pthread_cond_t cond_ready=PTHREAD_COND_INITIALIZER;
2. 等待条件成熟
* pthread_cond_wait(&cond_ready, &mut);
3. 设置条件成熟
* pthread_cond_signal(&cond_ready);
五、代码
/*
* Filename : pthread.c
* Date : 2017-04-24
* Author : Chen-nan
* Description: 这个程序是测试线程的互斥访问的。即:多个线程同时对一个资源进行访问时候,为了保证所操作资源的原子性,一次只能一个线程访问。
* */
* #include <pthread.h>
#include <unistd.h>
#include <stdio.h>
pthread_t pthread[2] ;
int count = 0 ;
pthread_mutex_t mutex ;
/*线程A的函数*/
void * funa( ) {
int i = 0 ;
for( i=0 ; i<10 ; ++i ) {
pthread_mutex_lock( &mutex ) ;
++count ;
printf( "chen is : %d \n" , count ) ;
pthread_mutex_unlock( &mutex ) ;
}
pthread_exit(NULL) ;
}
/*线程B的函数*/
void * funb( ) {
int i = 0 ;
for( i=0 ; i<5 ; ++i ) {
pthread_mutex_lock( &mutex ) ;
++count ;
printf( "nan is : %d \n" , count ) ;
pthread_mutex_unlock( &mutex ) ;
}
pthread_exit(NULL) ;
}
int main ( int argc , char **argv ) {
pthread_mutex_init( &mutex , NULL ) ;
/*创建线程A*/
pthread_create( &pthread[0] , NULL , funa , NULL ) ;
/*创建线程B*/
pthread_create( &pthread[1] , NULL , funb , NULL ) ;
/*等待线程A完成*/
pthread_join( pthread[0] , NULL ) ;
/*等待线程B完成*/
pthread_join( pthread[1] , NULL ) ;
return 0 ;
}
/*
* Filename : pthread.c
* Date : 2017-04-24
* Author : Chen-nan
* Description: 这个程序是测试线程的同步访问的。即:多个线程按照一定顺序先后执行。
* */
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
pthread_t pthread[2] ;
int count = 0 ;
pthread_mutex_t mutex ;
/*创建条件变量,其实就是创建一个信号,通过发送信号,唤醒其他进程。*/
pthread_cond_t flag=PTHREAD_COND_INITIALIZER;
/*线程A的函数*/
void * funa( ) {
int i = 0 ;
for( i=0 ; i<10 ; ++i ) {
pthread_mutex_lock( &mutex ) ;
++count ;
printf( "chen is : %d \n" , count ) ;
pthread_mutex_unlock( &mutex ) ;
if( 10==count ) {
printf( "--------chen is finish .-------------\n") ;
/*条件成熟,发送条件变量(信号)通过其他进程可以开工了*/
pthread_cond_signal( &flag ) ;
}
}
pthread_exit(NULL) ;
}
/*线程B的函数*/
void * funb( ) {
int i = 0 ;
pthread_mutex_lock( &mutex ) ;
if( 10>count ) {
/*判断当前条件是否可以执行,不行就挂起等待。直到有其他线程发送信号为止。这个函数包含了一个互斥锁,进入挂起状态时会解锁(所以前面有一个互斥锁的锁定),当收到信号后就会加上互斥锁(所以后边要解锁)。*/
pthread_cond_wait( &flag , &mutex ) ;
}
for( i=0 ; i<5 ; ++i ) {
++count ;
printf( "nan is : %d \n" , count ) ;
pthread_mutex_unlock( &mutex ) ;
}
pthread_exit(NULL) ;
}
int main ( int argc , char **argv ) {
pthread_mutex_init( &mutex , NULL ) ;
/*创建线程A*/
pthread_create( &pthread[0] , NULL , funa , NULL ) ;
/*创建线程B*/
pthread_create( &pthread[1] , NULL , funb , NULL ) ;
/*等待线程A完成*/
pthread_join( pthread[0] , NULL ) ;
/*等待线程B完成*/
pthread_join( pthread[1] , NULL ) ;
return 0 ;
}