信号量(semaphore)
信号量是一个计数器,用来控制访问临界资源的线程最大并行数量。当信号量的初始值为1时,效果等同于互斥量。
信号量不是最早的POSIX线程相关规范,因此信号量相关定义是在semaphore.h中。semaphore.h中定义的信号量,既可以用于线程,又可以用于进程。
信号量的使用步骤:
1、定义信号量 sem_t sem;
2、初始化信号量sem_init(&sem,0,计数初始值)
第二个参数为0,代表用于线程计数,其他值代表进程计数(进程计数目前Linux不支持)
3、获取信号量(减1)
sem_wait(&sem);
4、读写资源
5、释放信号量(加1)
sem_post(&sem);
6、删除信号量 sem_destroy(&sem);
死锁
mutex m1,m2;
init(m1);init(m2);
启动两个线程A、B;
A
lock(m1)
... <---运行到这个位置停止(时间片over)
lock(m2) <--- 运行到此阻塞,等待B线程释放m2
...
unlock(m2)
unlock(m1)
B
lock(m2)
... <---运行到此,没有问题
lock(m1) <---阻塞,等待A线程释放m1
...
unlock(m1)
unlock(m2)
多线程编程时,必须避免死锁 --- 线程之间互相锁定叫死锁。避免死锁的经验:
顺序上锁,反向解锁,不要回调。
#include <stdio.h> #include <pthread.h> #include <semaphore.h> char* data[5];//数组,存储名字 int size = 0;//当前人数,数组下标 sem_t sem; //pthread_mutex_t lock;//1 //=PTHREAD_MUTEX_INITIALIZER; void* task(void* p){ //pthread_mutex_lock(&lock);//3 sem_wait(&sem); data[size] = (char*)p;//4 sleep(1); size++; sem_post(&sem); //pthread_mutex_unlock(&lock);//5 } int main(){ data[size] = "zhangfei"; size++; pthread_t id1,id2; sem_init(&sem,0,1); pthread_create(&id1,0,task,"guanyu"); pthread_create(&id2,0,task,"zhaoyun"); pthread_join(id1,0); pthread_join(id2,0); //pthread_mutex_destroy(&lock);//5 sem_destroy(&sem); int i; for (i = 0;i < size;i++){ printf("%s\n",data[i]); } }
#include <stdio.h> #include <pthread.h> #include <semaphore.h> #include <time.h> //模拟访问某资源的最大连接数控制 sem_t sem; void* task(void* p){ int i = (int)p; printf("第%d个线程开始运行\n",i); sem_wait(&sem);//计算减1,如果计算已经为0,阻塞等待 printf("第%d线程连接成功\n",i); srand(time(0)); int res = rand() % 10; sleep(res); printf("第%d个线程连接结束,释放资源\n",i); sem_post(&sem); } int main(){ sem_init(&sem,0,10);//最多同时连接10个 int i; for (i = 1;i < 21;i++){ pthread_t id; pthread_create(&id,0,task,(void*)i); } while(1); }