在Linux操作系统中,进程间同步和互斥的机制有许多种,其中最常用的是信号量(Semaphore)。信号量是由Dijkstra首次引入的一种系统结构,其本质是一把锁,用于保护共享资源。在经典的生产者-消费者问题中,生产者和消费者进程之间需要共享一个缓冲区,因此需要使用信号量来保证缓冲区的正确性。
而在使用信号量时,一个非常重要的函数是sem_wt函数。这个函数的作用是阻塞当前进程,直到某一个信号量的值变得大于0。而当一个进程对信号量执行减操作时,如果信号量的值为0,那么该进程就会被阻塞,直到另外一个进程对信号量执行加操作将其值变为非0。
sem_wt的函数原型如下:
int sem_wt(sem_t *sem);
其中sem_t是一个信号量类型,表示一个信号量的实例,*sem则是具体的信号量变量。sem_wt函数的返回值为0表示函数执行成功;否则,就表示函数执行失败。
在实际使用时,sem_wt函数常常与sem_post函数配合使用。sem_post函数是另外一个信号量函数,用于增加信号量的值。通过调用sem_post函数,我们可以将一个被阻塞的进程唤醒,从而使其继续执行。注意:sem_wt和sem_post函数只能用于已经初始化的信号量上,否则将出现系统错误。
一般情况下,sem_wt函数是在临界区中调用的。在许多并发程序中,临界区是程序中需要互斥访问的临界资源,在进入临界区之前,应该对临界区进行加锁,当退出临界区时,再释放锁。sem_wt函数可以保证临界区不会同时被多个进程占用,从而保证临界区的数据正确性和一致性。
在信号量的应用中,sem_wt函数被广泛地用于等待共享资源的可用性。举例来说,假设有10个进程需要访问一个共享变量,但是这个变量只能同时被一个进程访问。这时,我们就可以使用一个信号量来实现对共享变量的互斥访问控制。当一个进程访问共享变量之前,需要获取信号量的内部资源,如果相应的信号量取得资源的量为0,则进程需要一直等待,直到资源可用。
sem_wt函数是Linux环境下实现进程同步和互斥机制的重要函数之一。通过使用这个函数,我们可以更加精确地控制进程的执行顺序和访问共享资源的安全性。对于需要进行并发编程的开发者来说,熟练掌握sem_wt函数的使用方法,是非常关键的一环。
相关问题拓展阅读:
帮你修改了一手搭下,编译运行没问题,修改的地方都标出来了,
由于不知道你程序的功能袜薯老,所以没有对你的程序逻辑进行分析
#include
#include
#include
#include
//–以下是修改的部分
sem_t in;
sem_t out;
sem_t handout;
sem_t handin;
sem_t goout;
//–
int counter=0;
void * studentIn(void *a)
{
sem_wait(&in);//修改
counter++;
printf(“%d\n”,counter);
if(counter==30)
{
sem_post(&handout);//告升修改
return NULL;
}
sem_post(&in);//修改
return NULL;
}
void * fteacherhandout(void *b)
{
sem_wait(&handout);//修改
printf(“teacher said:hand out over\n”);
sem_post(&handin);//修改
return NULL;
}
void * studentout(void *c)
{
sem_wait(&handin);//修改
sem_wait(&out);//修改
counter–;
printf(“%d\n”,counter);
if(counter==0)
{
sem_post(&goout);//修改
return NULL;
}
sem_post(&out);//修改
}
void * fteacherout(void *d)
{
sem_wait(&goout);//修改
printf(“teacher go out”);
return NULL;
}
void main()
{
int i=0;
//–以下是修改的部分
sem_init(&in,0,1);
sem_init(&out,0,1);
sem_init(&handin,0,0);
sem_init(&handout,0,0);
sem_init(&goout,0,0);
//
pthread_t thread1,thread2,teacher1,teacher2;
pthread_attr_t attr;
pthread_attr_init(&attr);
for(i=0;i
{
pthread_create(&thread1,&attr,studentIn,NULL);
}
for(i=0;i
{
pthread_create(&thread2,&attr,studentout,NULL);
}
pthread_create(&teacher1,&attr,fteacherhandout,NULL);
pthread_create(&teacher2,&attr,fteacherout,NULL);
return;
Linux 线程同步的橘蚂笑三种方法
线程的更大特点是资源的共享性,但资源共享中的同步问题是多线程编程的难点。linux下提供了多种方式来处理线程同步,最常用的是互斥锁、条件变量和信号量。
一、互斥锁(mutex)
通过锁机制实现线程间的同步。
初始化锁。在Linux下,线程的互斥量数据类型是pthread_mutex_t。在使用前,要对它进行初始化。
静态分配:pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
动态分配:int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutex_attr_t *mutexattr);
加锁。对共享资源的访问,要对互斥量进行加锁,如果互斥量已经上了锁,调用线程会阻塞,直到互斥量被解锁。
int pthread_mutex_lock(pthread_mutex *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
解锁。在完成了对共享资源的访问后,要对互斥量进行解锁。
int pthread_mutex_unlock(pthread_mutex_t *mutex);
销毁锁。锁在是使用完成后,需要进行销毁以释放资源。
int pthread_mutex_destroy(pthread_mutex *mutex);
view plain copy
#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;
}
view plain copy
#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);,再读取资源
//用这个流程是比较清楚的
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;
}
三、信号量(sem)
如同进程一样,线程也可以通过信号量来实现通信,虽然是轻量级的。信号量函数的名字都以”sem_”打头。线程使用的基本信号量函数有四个。
信号量初始化。
int sem_init (sem_t *sem , int pshared, unsigned int value);
这是对由sem指定的信号量进行初始化,设置好它的共享选项(linux 只支持为0,即表示它是当前进程的局部信号量),然后给它一个初始值VALUE。
等待信号量。给信号量减1,然后等待直到信号量的值大于0。
int sem_wait(sem_t *sem);
释放信号量。信号量值加1。并通知其他等待线程。
int sem_post(sem_t *sem);
销毁信号量。我们用完信号量后都它进行清理。归还占有的一切资源。
int sem_destroy(sem_t *sem);
view plain copy
#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;
}
香港服务器选创新互联,2H2G首月10元开通。
创新互联(www.cdcxhl.com)互联网服务提供商,拥有超过10年的服务器租用、服务器托管、云服务器、虚拟主机、网站系统开发经验。专业提供云主机、虚拟主机、域名注册、VPS主机、云服务器、香港云服务器、免备案服务器等。
分享标题:Linux下的sem_wait等待函数简介(linuxsemwait)
网页URL:http://www.mswzjz.cn/qtweb/news49/393549.html
攀枝花网站建设、攀枝花网站运维推广公司-贝锐智能,是专注品牌与效果的网络营销公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 贝锐智能