这天学的是多线程编程
进程被看作是两个实体
资源分配单元 (进程或者是任务)
调度/处理机分派单元 (线程或轻量级进程)
线程是进程中一个处理机分派的单元
一个线程可以访问它的进程的内存和资源,而且这些资源为同一进程的所有线程共享
用线程的好处
更少的生成时间
更少的删除时间
进程间切换更快
不用恢复用户地址空间
通信更有效
共享地址空间
不需调用内核传递消息
进程的所有资源对线程都可用
进程同步的主要任务:协调多个相关进程的执行次序
并发执行的诸进程之间能有效地共享资源和相互合作
程序的执行具有可再现性
实现方式
使用互斥量
数据类型:pthread_mutex_t
程序员给某个数据加锁
同一时间只允许一个线程去访问数据
pthread_mutex_init: 初始化一个互斥量
pthread_mutex_lock: 给一个互斥量加锁
pthread_mutex_trylock:加琐,如果失败不阻塞
pthread_mutex_unlock:解锁
作业1:
请设计程序,程序有一个共享变量,创建两个线程,各自把counter增加5000次.要求:两个线程是并发执行.
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <pthread.h>
#define NLOOP 10
pthread_mutex_t wm;
void *increase(void *vptr);
int print_count = 0;
int main(){
pthread_t a_thread;
pthread_t b_thread;
if(pthread_mutex_init(&wm,NULL)!=0){
perror("Mutex init failed");
exit(1);
}
pthread_create(&a_thread,NULL,&increase,NULL);
pthread_create(&b_thread,NULL,&increase,NULL);
pthread_join(a_thread,NULL);
pthread_join(b_thread,NULL);
return 0;
}
void *increase(void *vptr){
// if(pthread_mutex_lock(&wm)!=0){
int i,val;
for(i=0; i<NLOOP; i++){
pthread_mutex_lock(&wm);
val = print_count;
print_count = val + 1;
printf("%x count is %d \n",(unsigned int)pthread_self(),print_count,print_count);
pthread_mutex_unlock(&wm);
sleep(1);
}
}
互斥量的缺点
互斥量的缺点
互斥量需要时间来加锁和解锁
互斥量尽量少用,够用即可
每个互斥量保护的区域应尽量大
互斥量的本质是串行执行
如果很多线程需要频繁地加锁同一互斥量,则线程大部分时间都在等待-损害性能
互斥量保护的数据/代码包含彼此无关的片段-一个互斥量分解为几个小互斥量-任意时刻需要小互斥量的线程减少-减少线程的等待时间
互斥量应该足够多-有意义的地步
每个互斥量保护的区域应该尽量少
条件变量
条件变量是利用线程间共享的全局变量进行同步的一种机制
一个线程等待”条件变量的条件成立”而阻塞
另一线程改变了条件,它发信号给相关的条件变量,唤醒一个或多个等待它的线程
条件的检测在互斥锁的保护下进行
互斥锁用于短期等待
条件变量用于长期等待
使用条件变量之前要先进行初始化
进程间线程的通信
pthread_cond_t my_condition = PTHREAD_COND_INITIALIZER
调用系统函数
int pthread_cond_init(pthread_cond_t *cond,const pthread_condattr_t *attr)
释放为条件变量所分配的资源
int pthread_cond_destroy(pthread_cond_t *cond)
等待条件变量
int pthread_cond_wait(
pthread_cond_t *cond, pthread_mutex_t *mutex);
如果条件为假,调用线程自动阻塞,并释放等待状态改变的互斥锁.
如果另一个线程改变了条件,它发信号给关联的条件变量,唤醒一个或多个等待它的线程,重新获得互斥锁,重新评估条件.
一个生产者--消费者的例子
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define MAX 5
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
typedef struct
{
char buffer[MAX];
int how_many;
}BUFFER;
BUFFER share = {"",0};
char ch = 'A';
void *readFunc(void*);
void *writeFunc(void *);
int main(void)
{
pthread_t readThread;
pthread_t writeThread;
pthread_create(&readThread,NULL,readFunc,(void *)NULL);
pthread_create(&writeThread,NULL,writeFunc,(void *)NULL);
pthread_join(writeThread,(void **)NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
exit(0);
}
void *readFunc(void *junk)
{
int n = 0;
printf("Read Thread %2d:starting\n",pthread_self());
while(ch != 'Z')
{
pthread_mutex_lock(&mutex);
if(share.how_many != MAX)
{
share.buffer[share.how_many++] = ch++;
printf("Read Thread %2d: Got char[%c]\n",pthread_self(),ch-1);
if(share.how_many == MAX)
{
printf("Read Thread %2d: signaling full\n",pthread_self());
pthread_cond_signal(&cond);
}
}
pthread_mutex_unlock(&mutex);
}
sleep(1);
printf("Read Thread %2d: Exiting\n",pthread_self());
return NULL;
}
void *writeFunc(void *junk)
{
int i;
int n = 0;
printf("Write Thread %2d: starting\n",pthread_self());
while(ch != 'Z')
{
pthread_mutex_lock(&mutex);
printf("\nWrite Thread %2d: writing buffer\n",pthread_self());
while(share.how_many != MAX)
pthread_cond_wait(&cond,&mutex);
printf("Write Thread %2d: writing buffer\n",pthread_self());
for(i = 0; share.buffer[i]&&share.how_many;++i,share.how_many--)
putchar(share.buffer[i]);
pthread_mutex_unlock(&mutex);
}
printf("Write Thread %2d: exiting\n",pthread_self());
return NULL;
}