线程特点:
1.通常线程指的是共享相同地址空间的多个任务
2.使用多线程的好处
大大提高了任务切换的效率
避免了额外的TLB和cache的刷新
线程共享资源:
一个进程中的多个线程共享以下资源:
1.可执行的指令
2.静态数据
3.进程中打开的文件描述符
4.当前工作目录
5.用户ID
6.用户组ID
线程私有资源:
1.线程ID(TID)
2.pc(程序计数器)和相关寄存器
3.堆栈
4.错误号(errno)
5.优先级
6.执行状态和属性
Linux线程库:
·pthread线程库中提供以下操作
创建线程 回收线程 结束线程
·同步和互斥机制
信号量 互斥锁
使用线程库编译时
gcc -o test test.c -lpthread
线程创建——pthread_create:
#include <pthread.h>
int pthread_create(pthread_t *thread,const pthread_attr_t *attr,void *(*routine)(void*),void *arg);
成功时返回0,失败返回错误码
thread线程对象
attr线程属性,NULL代表默认属性
routine线程执行的函数
arg传递给routine的参数,不需要传参就NULL
线程回收——pthread_join
#include <pthread.h>
int pthread_join(pthread_t thread,void **retval);
成功时返回0,失败返回错误码
thread要回收的线程对象
调用线程阻塞直到thread结束
*retval接收线程thread的返回值
线程结束——pthread_exit
#include <pthread.h>
void pthread_exit(void *retval);
结束当前线程
retval可被其他线程通过pthread_join获取
线程私有资源被释放
示例:
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
char message[32] = "hello world";
void *thread_func(void *arg);
int main(int argc, char const *argv[])
{
pthread_t a_thread;
void *result;
if(pthread_create(&a_thread,NULL,thread_func,NULL) != 0)
{
printf("fail to pthread_create");
exit(-1);//表示程序异常退出。
}
pthread_join(a_thread,&result);
printf("message is %s\n", message);
return 0;
}
void *thread_func(void *arg)
{
sleep(1);
strcpy(message,"marked by thread");
pthread_exit("thank you fo waiting for me");
}
线程间通信:
·线程共享同一进程的地址空间
优点:
线程间通信容易 通过全局变量交换数据
缺点:
多个线程访问共享数据时需要同步或互斥机制
信号量:
信号量代表某一类资源,其值表示系统中该资源的数量
信号量是一个受保护的变量,只能通过三种操作来访问
1.初始化
2.P操作(申请资源)
3.V操作(释放资源)
posix中定义了两类信号量
无名信号量 有名信号量
信号量初始化:
#include <semaphore.h>
int sem_init(sem_t *sem,int pshared,unsigned int val);
成功时返回0.失败返回EOF
sem指向要初始化的信号量
pashared:0 线程间 1 进程间
val 信号量初始值 0:没有资源 大于0 有资源
P / V操作:
#include <semaphore.h>
int sem_wait(sem_t *sem); P操作
int sem_post(sem_t *sem); V操作
成功返回0,失败返回EOF
sem指向要操作的信号量对象
互斥:
·临界资源:
一次只允许一个任务(进程,线程)访问的共享资源
·临界区:
访问临界区的代码
·互斥机制:
mutex互斥锁
访问临界资源前申请锁,访问完后释放锁
互斥锁初始化:
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutexattr_t *attr);
成功返回0,失败返回错误码
mutex指向要初始化的互斥锁对象
attr 互斥锁属性,NULL表述缺省属性
申请锁:
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);
成功返回0,失败返回错误码
mutex指向要初始化的互斥锁对象
如果无法获得锁,任务阻塞
释放锁:
#include <pthead.h>
int pthread_mutex_unlock(pthread_mutex_t *mutex);
成功返回0,失败返回错误码
mutex 指向要初始化的互斥锁对象
执行完临界区要及时释放锁 示例:
互斥锁_LOCK_宏定义
编译时:
gcc -o test test.c -D_LOCK_
//-D 表示加入宏定义
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
unsigned int count,value1,value2;
pthread_mutex_t lock;
void *function(void *arg);
int main(int argc, char const *argv[])
{
pthread_t a_thread;
if(pthread_mutex_init(&lock,NULL) != 0)
{
printf("fail to pthread_mutex_init \n");
exit(-1);
}
if (pthread_create(&a_thread,NULL,function,NULL) != 0)
{
printf("fail to pthread_create");
exit(-1);//表示程序异常退出。
}
while(1)
{
count++;
#ifdef _LOCK_
pthread_mutex_lock(&lock);
#endif
value1 = count;
value2 = count;
#ifdef _LOCK_
pthread_mutex_unlock(&lock);
#endif
}
return 0;
}
void *function(void *arg)
{
while(1)
{
#ifdef _LOCK_
pthread_mutex_lock(&lock);
#endif
if(value1 != value2)
{
printf("value1 = %u ,value2 = %u \n",value1.value2);
usleep(100000);
}
#ifdef _LOCK_
pthread_mutex_unlock(&lock);
#endif
}
return NULL;
}