举例说明C:语言中Sem_init函数用法

906 阅读6分钟

Sem_init()函数的作用是初始化一个未命名的信号通路。现在问题来了:什么是semaphore?Semaphore是一个涉及到进程或线程同步的概念。semaphore是一种数据结构,用于同步进程,协助线程在不与其他线程交互的情况下一起继续运行。Linux支持的信号灯类型是POSIX信号灯。POSIX是作为操作系统的一个可移植接口。C POSIX有一个用标准C构建的包库,POSIX为那些在C标准中使用的程序增加了一些额外的功能。

为什么要使用信号灯?

在使用线程时,我们会遇到一些涉及竞赛条件的问题。这发生在两个或更多的线程同时需要相同的数据或信息而导致冲突的情况下。因此,为了避免这种类型的冲突情况,我们使用信号灯。有三种主要类型的信号灯。一种是二进制信号灯,另一种是计数信号灯。

我们在semaphore的范围内使用不同的函数,如sem_wait、sem_post和sem_init。sem_init是本文进一步考虑的主题。

Sem_init

正如我们上面所讨论的,为了初始化线程中的信号,我们使用sem_init函数。在这里,我们使用一个标志或标语来标识与fork()过程共享semaphore的情况。

语法

# sem_init(sem *sem, int pshared,  int value (unsigned));

sem:该功能协助信号灯处于就绪状态。

Pshared:这个参数在semaphore的声明中至关重要。因为它决定了新初始化的信号灯的状态。它是否应该在进程或线程之间共享。如果该值为非零,说明该信号在两个或多个进程之间共享,如果该值为零,则说明该信号在线程之间共享。

:它指定了最初分配给新创建的semaphore的值。

sem_init的执行

为了在C程序中执行信号灯,我们需要一个GCC编译器。但这是不够的。"-lpthread "是用来执行代码的。'a.c'是文件名。另一点是,在这里我们使用'.out'与文件名,而不是独立使用文件。

例子1

首先,我们添加了两个库,分别是semaphores和pthread,以适应c包的使用。像sem_init一样,其他信号也在这个程序中使用;在这里,我们将讨论它们。

Sem_wait ()

这个函数用来保持一个信号灯或继续等待。如果提供给semaphore的值为负数,则调用被阻止,循环被关闭。而其他任何线程,当被调用时,被阻塞的信号灯被唤醒。

Sem_post()

Sem_post方法用于增加信号灯的值。当sem_post被调用时,该值会被增加。

Sem_destroy()

如果我们想销毁信号灯,我们使用sem_destroy方法。现在再次关注一下这里提供的源代码。首先,这里使用了 "await "函数。它将使线程先等待,以便其他人可以执行任务。在调用该函数时,会显示一条信息,说明该线程已进入。之后,一个 "sleep "函数被调用5秒。

根据主函数创建了两个线程,2个线程被创建,但第一个线程在获得锁后睡眠5秒。所以第二个线程在被调用时并没有进入。当它被调用时,它将在5-2秒后进入。

Sem_post将在睡眠函数之后工作;sem_post将工作并显示一个完整的状态信息。在主程序中,首先初始化semaphore,然后用pthread创建两个线程。我们使用pthread_join函数来加入线程。而在最后,信号灯被销毁。

保存以.c为扩展名的文件;代码将被编译,并被执行。在执行过程中,你会看到第一条信息被显示出来,然后需要几秒钟才能完成,因为我们已经提供了5秒钟的睡眠函数,所以在这段时间之后,第一个线程的第二条信息被显示出来。

经常显示第二个线程的第一条信息。

第二条信息又需要时间来进行。

示例2

在走向第二个例子之前,首先,我们需要了解读者作者问题的概念。假设一个你想在进程之间共享的数据库在并发地运行。其中一些进程或线程可能只读该数据库。同时,其他人可能喜欢修改数据库。我们通过将第一个进程声明为读者,将第二个进程声明为写者来区分这两者。如果两个读者访问共享数据,将不会造成任何影响。

为了尽量减少这类困难的发生,我们需要协助写者访问共享数据库,在其中进行写作。这个问题是同步的,被称为读者-写者问题。

这个问题有很多变化。第一个处理的问题是,除非写者使用共享对象,否则没有读者会等待。

这个程序提供了第一个读者-写者问题的解决方案。在这个C源代码中,我们使用了10个读者和5个程序来演示这个解决方案。前两个计数器的取值被称为零。非读者确定了读者的数量。走向写者函数,这里使用了两个信号函数,第一个是等待,后一个是发布。这将显示写者的号码。

在写者函数之后,读者函数在这里被声明。写者将修改数据库,所以读者不能进入或改变任何由锁获得的东西。

# Pthread_mutex_lock(&mutex);

然后,非读者计数被递增。这里应用了一个if-statement的检查。如果数值为1,意味着它是第一个读者,这样写者就会被阻断。如果非阅读者的值为0,经过检查,这意味着它是最后一个阅读者,所以我们现在将允许写入者进行修改。

# Pthread_mutex_unlock(&mutex);

我们将在读取器和写入器函数之后向主程序移动。这里我们已经初始化了10个读者和5个写者。sem_init函数将初始化semaphore。在这里,For循环被分别用于读者和写者。Pthread_create将创建读和写函数。此外,pthread_join将连接线程。每个for循环将为写者使用5次联合,然后为读者使用10次。

最后,在使用结束后,信号灯将被分别销毁。编译该代码,然后执行它。你会看到,读者的随机数是在10个数组大小内产生的,计数为1。而对于写者来说,有5个数字被修改。

总结

sem_init "一文是多线程过程中semaphores使用的一个函数,用于对同时发生的任务进行优先排序。还有许多与信号灯有关的其他函数,也在此讨论。我们已经解释了两个基本的例子来阐述sem_init在函数中的用法和其他功能。