Semaphore是一种用于保护对共享资源的访问的技术,在多任务或多线程环境中使用。Linux系统提供了一组函数来支持Semaphore,也就是sem_init、sem_wt、sem_post和sem_destroy等函数。本文将深入探究这组函数的使用方法和注意事项。
陵水黎族ssl适用于网站、小程序/APP、API接口等需要进行数据传输应用场景,ssl证书未来市场广阔!成为成都创新互联的ssl证书销售渠道,可以享受市场价格4-6折优惠!如果有意向欢迎电话联系或者加微信:18982081108(备注:SSL证书合作)期待与您的合作!
1. Semaphore的定义
Semaphore是一种计数器,用于在多个进程之间共享资源。在Linux系统中,Semaphore被定义为结构体sem_t。Semaphore的值表示可用资源的数量。如果在一个进程中使用某个资源,则Semaphore的计数器将减少。当Semaphore值为0时,表示没有可用资源,进程必须等待资源变得可用。
Semaphores可以使用两种方式创建。之一种方式是在运行时创建,使用sem_init函数来创建。第二种方式是在系统启动时创建,然后存储在共享内存中。Linux使用IPCs来实现这种类型的semaphores。
2. Semaphore函数
2.1 sem_init函数
sem_init函数用于初始化Semaphore,它需要三个参数。之一个参数是一个sem_t结构体指针。第二个参数是指定Semaphore的进程间共享的方式,可以是PTHREAD_PROCESS_PRIVATE或者PTHREAD_PROCESS_SHARED。第三个参数是Semaphore的值,表示初始资源数量。
函数原型为:
int sem_init(sem_t *sem, int pshared, unsigned int value);
2.2 sem_wt函数
sem_wt函数用于在Semaphore减少之前等待Semaphore值变得大于0。当Semaphore的值为0时,这个函数将一直等待。一旦Semaphore值大于0,则函数将Semaphore的值减1,并返回。
函数原型为:
int sem_wt(sem_t *sem);
2.3 sem_post函数
sem_post函数用于将Semaphore的值加1,并唤醒等待的进程或线程。 Semaphore的值可能增加后,调用sem_post函数将返回。
函数原型为:
int sem_post(sem_t *sem);
2.4 sem_destroy函数
sem_destroy函数用于释放Semaphore资源。此函数需要一个sem_t结构体指针作为参数。
函数原型为:
int sem_destroy(sem_t *sem);
3. 使用Semaphore函数的注意事项
1)在使用Semaphore的过程中,需要确保在进程或线程间的修改Semaphore值是互斥的,避免访问同一资源。
2)在使用Semaphore时,需要思考如何设置初始值,避免因赋给一个错误的初始值而导致的死锁。
3)需要考虑多个Semaphore同时使用时可能存在的死锁情况。
4)在多线程环境中使用Semaphore时,需要注意线程安全问题,如果线程使用了相同的Semaphore,则需要对Semaphore进行保护。
5)在进程退出前,需要调用sem_destroy函数释放Semaphore资源。
4.
Semaphore是一种用于在多线程或多任务环境享资源的技术。在Linux操作系统中,提供了一组函数用于支持Semaphore,包括sem_init、sem_wt、sem_post和sem_destroy等函数。在使用Semaphore的过程中,需要注意安全性和死锁等问题,确保资源共享的正确性和稳定性。
成都网站建设公司-创新互联为您提供网站建设、网站制作、网页设计及定制高端网站建设服务!
朋友你好:希望能帮到你。互相学习。
线程的更大特点是资源的共享性,但资源共享中的同步问题是多线程编程的难点。清敏linux下提供了多种方式来处理线程裂做同步,最常用的是互斥锁、条件变量和信号量。
1)互斥锁(mutex)
通过锁机制实现线程间的同步。同一时刻只允许一个肆正衡线程执行一个关键部分的代码。
int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutex_attr_t *mutexattr);
int pthread_mutex_lock(pthread_mutex *mutex);
int pthread_mutex_destroy(pthread_mutex *mutex);
int pthread_mutex_unlock(pthread_mutex *
(1)先初始化锁init()或静态赋值pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIER
attr_t有:
PTHREAD_MUTEX_TIMED_NP:其余线程等待队列
PTHREAD_MUTEX_RECURSIVE_NP:嵌套锁,允许线程多次加锁,不同线程,解锁后重新竞争
PTHREAD_MUTEX_ERRORCHECK_NP:检错,与一同,线程请求已用锁,返回EDEADLK;
PTHREAD_MUTEX_ADAPTIVE_NP:适应锁,解锁后重新竞争
(2)加锁,lock,trylock,lock阻塞等待锁,trylock立即返回EBUSY
(3)解锁,unlock需满足是加锁状态,且由加锁线程解锁
(4)清除锁,destroy(此时锁必需unlock,否则返回EBUSY,//Linux下互斥锁不占用内存资源
示例代码
#include
#include
#include
#include
#include “iostream”
using namespace std;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int tmp;
void* thread(void *arg)
{
cout
#include
#include “stdlib.h”
#include “unistd.h”
pthread_mutex_t mutex;
pthread_cond_t cond;
void hander(void *arg)
{
free(arg);
(void)pthread_mutex_unlock(&mutex);
}
void *thread1(void *arg)
{
pthread_cleanup_push(hander, &mutex);
while(1)
{
printf(“thread1 is running\n”);
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);
printf(“thread1 applied the condition\n”);
pthread_mutex_unlock(&mutex);
sleep(4);
}
pthread_cleanup_pop(0);
}
void *thread2(void *arg)
{
while(1)
{
printf(“thread2 is running\n”);
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);
printf(“thread2 applied the condition\n”);
pthread_mutex_unlock(&mutex);
sleep(1);
}
}
int main()
{
pthread_t thid1,thid2;
printf(“condition variable study!\n”);
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cond,NULL);
pthread_create(&thid1,NULL,thread1,NULL);
pthread_create(&thid2,NULL,thread2,NULL);
sleep(1);
do
{
pthread_cond_signal(&cond);
}while(1);
sleep(20);
pthread_exit(0);
return 0;
}
示例程序2:
#include
#include
#include “stdio.h”
#include “stdlib.h”
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
struct node
{
int n_number;
struct node *n_next;
} *head = NULL;
/**/
static void cleanup_handler(void *arg)
{
printf(“Cleanup handler of second thread./n”);
free(arg);
(void)pthread_mutex_unlock(&mtx);
}
static void *thread_func(void *arg)
{
struct node *p = NULL;
pthread_cleanup_push(cleanup_handler, p);
while (1)
{
//这个mutex主要是用来保证pthread_cond_wait的并发性
pthread_mutex_lock(&mtx);
while (head == NULL)
{
//这个while要特别说明一下,单个pthread_cond_wait功能很完善,为何
//这里要有一个while (head == NULL)呢?因为pthread_cond_wait里的线
//程可能会被意外唤醒,如果这个时候head != NULL,则不是我们想要的情况。
//这个时候,应该让线程继续进入pthread_cond_wait
// pthread_cond_wait会先解除之前的pthread_mutex_lock锁定的mtx,
//然后阻塞在等待对列里休眠,直到再次被唤醒(大多数情况下是等待的条件成立
//而被唤醒,唤醒后,该进程会先锁定先pthread_mutex_lock(&mtx);,再读取资源
//用这个流程是比较清楚的/*block–>unlock–>wait() return–>lock*/
pthread_cond_wait(&cond, &mtx);
p = head;
head = head->n_next;
printf(“Got %d from front of queue/n”, p->n_number);
free(p);
}
pthread_mutex_unlock(&mtx); //临界区数据操作完毕,释放互斥锁
}
pthread_cleanup_pop(0);
return 0;
}
int main(void)
{
pthread_t tid;
int i;
struct node *p;
//子线程会一直等待资源,类似生产者和消费者,但是这里的消费者可以是多个消费者,而
//不仅仅支持普通的单个消费者,这个模型虽然简单,但是很强大
pthread_create(&tid, NULL, thread_func, NULL);
sleep(1);
for (i = 0; i n_number = i;
pthread_mutex_lock(&mtx); //需要操作head这个临界资源,先加锁,
p->n_next = head;
head = p;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mtx); //解锁
sleep(1);
}
printf(“thread 1 wanna end the line.So cancel thread 2./n”);
//关于pthread_cancel,有一点额外的说明,它是从外部终止子线程,子线程会在最近的取消点,退出
//线程,而在我们的代码里,最近的取消点肯定就是pthread_cond_wait()了。
pthread_cancel(tid);
pthread_join(tid, NULL);
printf(“All done — exiting/n”);
return 0;
}
3)信号量
如同进程一样,线程也可以通过信号量来实现通信,虽然是轻量级的。
信号量函数的名字都以”sem_”打头。线程使用的基本信号量函数有四个。
#include
int sem_init (sem_t *sem , int pshared, unsigned int value);
这是对由sem指定的信号量进行初始化,设置好它的共享选项(linux 只支持为0,即表示它是当前进程的局部信号量),然后给它一个初始值VALUE。
两个原子操作函数:
int sem_wait(sem_t *sem);
int sem_post(sem_t *sem);
这两个函数都要用一个由sem_init调用初始化的信号量对象的指针做参数。
sem_post:给信号量的值加1;
sem_wait:给信号量减1;对一个值为0的信号量调用sem_wait,这个函数将会等待直到有其它线程使它不再是0为止。
int sem_destroy(sem_t *sem);
这个函数的作用是再我们用完信号量后都它进行清理。归还自己占有的一切资源。
示例代码:
#include
#include
#include
#include
#include
#include
#define return_if_fail(p) if((p) == 0){printf (“:func error!/n”, __func__);return;}
typedef struct _PrivInfo
{
sem_t s1;
sem_t s2;
time_t end_time;
}PrivInfo;
static void info_init (PrivInfo* thiz);
static void info_destroy (PrivInfo* thiz);
static void* pthread_func_1 (PrivInfo* thiz);
static void* pthread_func_2 (PrivInfo* thiz);
int main (int argc, char** argv)
{
pthread_t pt_1 = 0;
pthread_t pt_2 = 0;
int ret = 0;
PrivInfo* thiz = NULL;
thiz = (PrivInfo* )malloc (sizeof (PrivInfo));
if (thiz == NULL)
{
printf (“: Failed to malloc priv./n”);
return -1;
}
info_init (thiz);
ret = pthread_create (&pt_1, NULL, (void*)pthread_func_1, thiz);
if (ret != 0)
{
perror (“pthread_1_create:”);
}
ret = pthread_create (&pt_2, NULL, (void*)pthread_func_2, thiz);
if (ret != 0)
{
perror (“pthread_2_create:”);
}
pthread_join (pt_1, NULL);
pthread_join (pt_2, NULL);
info_destroy (thiz);
return 0;
}
static void info_init (PrivInfo* thiz)
{
return_if_fail (thiz != NULL);
thiz->end_time = time(NULL) + 10;
sem_init (&thiz->s1, 0, 1);
sem_init (&thiz->s2, 0, 0);
return;
}
static void info_destroy (PrivInfo* thiz)
{
return_if_fail (thiz != NULL);
sem_destroy (&thiz->s1);
sem_destroy (&thiz->s2);
free (thiz);
thiz = NULL;
return;
}
static void* pthread_func_1 (PrivInfo* thiz)
{
return_if_fail (thiz != NULL);
while (time(NULL) end_time)
{
sem_wait (&thiz->s2);
printf (“pthread1: pthread1 get the lock./n”);
sem_post (&thiz->s1);
printf (“pthread1: pthread1 unlock/n”);
sleep (1);
}
return;
}
static void* pthread_func_2 (PrivInfo* thiz)
{
return_if_fail (thiz != NULL);
while (time (NULL) end_time)
{
sem_wait (&thiz->s1);
printf (“pthread2: pthread2 get the unlock./n”);
sem_post (&thiz->s2);
printf (“pthread2: pthread2 unlock./n”);
sleep (1);
}
return;
}
通 过执行结果后,可以看出,会先执行线程二的函数,然后再执行线程一的函数。它们两就实现了同步
创新互联-老牌IDC、云计算及IT信息化服务领域的服务供应商,业务涵盖IDC(互联网数据中心)服务、云计算服务、IT信息化、AI算力租赁平台(智算云),软件开发,网站建设,咨询热线:028-86922220
当前标题:深入探究LinuxSemaphore函数(linuxsemaphore函数)
标题URL:http://www.csdahua.cn/qtweb/news6/408856.html
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网