续接上一部分线程通信(一)的内容
线程的同步和互斥:
进行多线程编程,因为无法知道哪个线程会在哪个时候对共享资源进行操作,因此让如何保护共享资源变得复杂,通过下面这些技术的使用,可以解决
线程之间对资源的竞争:
1. 互斥量Mutex
2. 信号灯Semaphore
3. 条件变量Conditions
mutex互斥锁线程控制
互斥锁是用一种简单的加锁方法来控制对共享资源的原子操作。
互斥锁只有两种状态,也就是上锁和解锁,可以把互斥锁看作某种意义上的全局变量。
在同一时刻只能有一个线程掌握某个互斥锁,拥有上锁状态的线程能够对共享资源进行操作。若其他线程希望上锁一个已经被上锁的互斥锁,则该线程就会挂起,直到上锁的线程释放掉互斥锁为止。
互斥锁可以分为快速互斥锁、递归互斥锁和检错互斥锁。
这三种锁的区别主要在于其他未占有互斥锁的线程在希望得到互斥锁时是否需要阻塞等待。
快速锁是指调用线程会阻塞直至拥有互斥锁的线程解锁为止。
递归互斥锁能够成功地返回,并且增加调用线程在互斥上加锁的次数,
而检错互斥锁则为快速互斥锁的非阻塞版本,它会立即返回并返回一个错误信息。
默认属性为快速互斥锁。
互斥锁线程控制
线程之间的同步和互斥
Pthread_mutex_init()
函数的作用:互斥锁的初始化
函数的头文件:#include <semaphore.h>
函数的原型:int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr *attr)
函数的参数:
Mutex:互斥锁
Mutexattr:PIHREAD_MUTEX_INITIALIZER 快速互斥锁
函数的返回值:
成功:返回 0
出错: 返回 < 0
作用:对互斥锁上锁、判断上锁、解锁、清除互斥锁
互斥锁上锁:pthread_mutex_lock(pthread_mutex_t *mutex)
互斥锁判断上锁:pthread_mutex_trylock(pthread_mutex_t *mutex)
互斥锁接锁:pthread_mutex_unlock(pthread_mutex_t *mutex)
消除互斥锁:pthread_mutex_destroy(pthread_mutex_t *mutex)
函数的返回值:
成功: 0 出错: -1
示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define THREAD_NUM 3
#define REPEAT_NUM 3
#define DELAY_TIME_LEVELS 6.0
pthread_mutex_t mutex;
void *thrd_func(void *arg)
{
int thrd_num = (int)arg;
int delay_time =0, count=0;
int res;
/*线程上锁*/
res = pthread_mutex_lock(&mutex);
printf("Thread %d is starting\n", thrd_num);
for(count=0; count<REPEAT_NUM; count++)
{
printf("\tThread %d:job %d delay=%d\n", thrd_num,count);
}
printf("Thread %d finish\n", thrd_num);
/*线程解锁*/
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
int main(void)
{
pthread_t thread[THREAD_NUM];
int no=0, res;
void *thrd_ret;
pthread_mutex_init(&mutex, NULL);
for(no=0; no<THREAD_NUM; no++)
{
res=pthread_create(&thread[no], NULL, thrd_func, (void *)no);
}
printf("creatr threads success\nwaiting for threads to finish....\n");
for(no=0; no<THREAD_NUM; no++)
{
res=pthread_join(thread[no], &thrd_ret);
}
pthread_mutex_destroy(&mutex); <span style="font-family:Calibri;">/*销毁线程*/</span>
return 0;
}
Sem_init()
函数的作用:初始化信号
函数的头文件:#include <semaphore.h>
函数的原型:int sem_init(sem_t *sem, int pshare, unsigned int value)
函数的参数:
Pshare:0
Sem:信号量指针
Value:信号里初始化
函数的返回值:
成功:返回0
出错:返回 -1
信号量的PV操作:
函数的原型:
Int sem_wait(sem_t *sem)------------P操作
Int sem_trywait(sem_t *sem)
Int sem_post(sem_t *sem)------------V操作
Int sem_getvalue(sem_t *sem)
Int sem_destroy(sem_t *sem)
函数的参数:
Sem:信号里指针
示例代码:线程的PV操作
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <sys/ipc.h>
#include <semaphore.h>
#include <fcntl.h>
int buff;
sem_t mutex,full;
int fd;
void inputnumber(void *arg);
void countnumber(void *arg);
int main()
{
pthread_t id1,id2;
pthread_t mon_th_id;
int ret;
/*创建信号量*/
ret=sem_init(&mutex,0,1);
ret+=sem_init(&full,0,0);
if(ret!=0)
{
perror("sem_init");
}
ret=pthread_create(&id1,NULL,(void *)inputnumber,NULL);
if(ret!=0)
perror("pthread cread1");
ret=pthread_create(&id2,NULL,(void *)countnumber,NULL);
if(ret!=0)
perror("pthread cread2");
pthread_join(id1,NULL);
pthread_join(id2,NULL);
exit(0);
}
void inputnumber(void *arg)
{
while(1)
{
sem_wait(&mutex);//使用sem_wait(3RT)可以阻塞调用线程,直到sem所指示的信号计数大于零为止
buff=0;
scanf("%d",&buff);
if(buff==0||buff>100||buff<0)
{
exit(-1);
}
printf("the input number is %d\n",buff);
sem_post(&full);//线程解除阻塞
}
}
void countnumber(void *arg)
{
while(1)
{
sem_wait(&full);//阻塞操作使用sem_wait(3RT)可以阻塞调用线程,直到sem所指示的信号计数大于零为止
printf("the square is:%d\n",buff*buff);
sem_post(&mutex);
}
}