1.信号量和互斥锁的使用场合
锁的特性就是保护临界资源的,一个线程A加锁,另一个线程B解锁,不合常理。A正在操作临界资源,B把A对临界资源的操作权限去除了……
线程间同步”的使用方法可以使用条件变量或者是信号量实现而不要使用mutex锁,mutex锁一般被用在保护线程间临界资源的情况下。
总结:sem_post(), sem_wait()实现线程同步。
pthread_mutex_lock,pthread_mutex_unlock实现防止临界资源竞态访问。
2.POSIX标准定义的信号量
int sem_init (sem_t *sem, int pshared, unsigned int value);
功能:初始化信号量
返回值:创建成功返回0,失败返回-1
参数sem:指向信号量结构的一个指针
参数pshared:不为0时此信号量在进程间共享,为0时当前进程的所有线程共享
参数value:信号量的初始值
int sem_destroy(sem_t * sem)
功能:释放信号量自己占用的一切资源 (被注销的信号量sem要求:没有线程在等待该信号量了)
返回值:满足条件 成功返回0,否则返回-1且置errno为EBUSY
参数sem:指向信号量结构的一个指针
int sem_post(sem_t * sem)
功能:它的作用来增加信号量的值。给信号量加1。
返回值:操作成功返回0,失败则返回-1且置errno
参数sem:指向信号量结构的一个指针
int sem_wait(sem_t * sem)
功能:它的作用是从信号量的值减去一个“1”,但它永远会先等待该信号量为一个非零值(大于0)才开始做减法。(如果对一个值为0的信号量调用sem_wait(),这个函数就会等待,直到有其它线程增加了信号量这个值使它不再是0为止,再进行减1操作。)
返回值:操作成功返回0,失败则返回-1且置errno
参数sem:指向信号量结构的一个指针
int sem_trywait(sem_t * sem)
功能:sem_trywait()为sem_wait()的非阻塞版,不进行等待
返回值:如果信号量计数大于0,则信号量立即减1并返回0,否则立即返回-1,errno置为EAGAIN
参数sem:指向信号量结构的一个指针
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout)
功能:带超时的sem_wait
int sem_getvalue(sem_t * sem, int * sval)
功能: 读取sem中信号量计数
返回值: 操作成功返回0,失败则返回-1且置errno
参数sem:指向信号量结构的一个指针
参数sval:信号量计数值
在linux中定义位置usr/include/semaphore.h
测试:
#include <semaphore.h> #include <pthread.h> #include <stdio.h> #include <stdlib.h> sem_t sem1; sem_t sem2; void *a_fn(void *arg) { sem_wait(&sem1); printf("thread a running\n"); return (void *)0; } void *b_fn(void *arg) { sem_wait(&sem2); sem_post(&sem1); printf("thread b running\n"); return (void *)0; } void *c_fn(void *arg) { sem_post(&sem2); printf("thread c running\n"); return (void *)0; } int main(void) { pthread_t a, b ,c; sem_init(&sem1, 0, 0); sem_init(&sem2, 0, 0); pthread_create(&a, NULL, a_fn, (void *)0); pthread_create(&b, NULL, b_fn, (void *)0); pthread_create(&c, NULL, c_fn, (void *)0); pthread_join(a, NULL); pthread_join(b, NULL); pthread_join(c, NULL); sem_destroy(&sem1); sem_destroy(&sem2); return 0; }
3.POSIX标准定义的互斥锁
这里不做太多描述,主线程和子线程访问竞态资源变量g_buf,加mutex进行保护。
#include <pthread.h> #include <stdio.h> #include <unistd.h> #include <semaphore.h> #include <string.h> static char g_buf[1000]; static sem_t g_sem; static pthread_mutex_t g_tMutex = PTHREAD_MUTEX_INITIALIZER; static void *my_thread_func (void *data) { while (1) { //sleep(1); /* 等待通知 */ //while (g_hasData == 0); sem_wait(&g_sem); /* 打印 */ pthread_mutex_lock(&g_tMutex); printf("recv: %s\n", g_buf); pthread_mutex_unlock(&g_tMutex); } return NULL; } int main(int argc, char **argv) { pthread_t tid; int ret; char buf[1000]; sem_init(&g_sem, 0, 0); /* 1. 创建"接收线程" */ ret = pthread_create(&tid, NULL, my_thread_func, NULL); if (ret) { printf("pthread_create err!\n"); return -1; } /* 2. 主线程读取标准输入, 发给"接收线程" */ while (1) { fgets(buf, 1000, stdin); pthread_mutex_lock(&g_tMutex); memcpy(g_buf, buf, 1000); pthread_mutex_unlock(&g_tMutex); /* 通知接收线程 */ sem_post(&g_sem); } return 0; }
相关函数:
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
4.POSIX标准定义的条件变量
#include <pthread.h> #include <stdio.h> #include <unistd.h> #include <semaphore.h> #include <string.h> static char g_buf[1000]; static pthread_mutex_t g_tMutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t g_tConVar = PTHREAD_COND_INITIALIZER; static void *my_thread_func (void *data) { while (1) { //sleep(1); /* 等待通知 */ //while (g_hasData == 0); pthread_mutex_lock(&g_tMutex); pthread_cond_wait(&g_tConVar, &g_tMutex); /* 打印 */ printf("recv: %s\n", g_buf); pthread_mutex_unlock(&g_tMutex); } return NULL; } int main(int argc, char **argv) { pthread_t tid; int ret; char buf[1000]; /* 1. 创建"接收线程" */ ret = pthread_create(&tid, NULL, my_thread_func, NULL); if (ret) { printf("pthread_create err!\n"); return -1; } /* 2. 主线程读取标准输入, 发给"接收线程" */ while (1) { fgets(buf, 1000, stdin); pthread_mutex_lock(&g_tMutex); memcpy(g_buf, buf, 1000); pthread_cond_signal(&g_tConVar); /* 通知接收线程 */ pthread_mutex_unlock(&g_tMutex); } return 0; }
①创建和销毁条件变量
// 初始化条件变量
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr); //cond_at tr 通常为 NULL
int pthread_cond_destroy(pthread_cond_t *cond);
②等待条件变量
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); //这需要结合互斥量一起使用
③ 通知条件变量
int pthread_cond_signal(pthread_cond_t *cond);
5.线程的退出与回收
①线程主动退出
void pthread_exit(void *retval);
在退出时候可以传递一个 void*类 型的数据带给主线程,若选择不传出数据,可将参数填充为 NULL。
②线程被动退出
pthread_cancel(pthread_t thread);
成功:返回 0 该函数传入一个 tid 号,会强制退出该 tid 所指向的线程,若成功执行会返 回 0。
③线程资源回收(阻塞)
int pthread_join(pthread_t thread, void **retval);
该函数为线程回收函数,默认状态为阻塞状态,直到成功回收线程后才返回。第一个参数为要回收线程的 tid 号,第二个参数为线程回收后接受线程传 出的数据。
④线程资源回收(非阻塞方式)
int pthread_tryjoin_np(pthread_t thread, void **retval);
#define _GNU_SOURCE #include <pthread.h> #include <stdio.h> #include <unistd.h> #include <errno.h> void *fun1(void *arg) { printf("Pthread:1 come!\n"); while(1){ sleep(1); } } void *fun2(void *arg) { printf("Pthread:2 come!\n"); pthread_cancel((pthread_t )(long)arg); pthread_exit(NULL); } int main() { int ret,i,flag = 0; void *Tmp = NULL; pthread_t tid[2]; ret = pthread_create(&tid[0],NULL,fun1,NULL); if(ret != 0){ perror("pthread_create"); return -1; } sleep(1); ret = pthread_create(&tid[1],NULL,fun2,(void *)tid[0]); if(ret != 0){ perror("pthread_create"); return -1; } while(1){ for(i = 0;i <2;i++){ if(pthread_tryjoin_np(tid[i],NULL) == 0){ printf("Pthread : %d exit !\n",i+1); flag++; } } if(flag >= 2) break; } return 0; }
标签:变量,int,void,信号量,互斥,mutex,pthread,线程,sem From: https://www.cnblogs.com/fuzidage/p/17006377.html