Linux 公平:在哪里可以更好地处理?

Linux 公平:在哪里可以更好地处理?,linux,Linux,我想在这里分享我的多道程序设计实践经验 昨天我写了一个多道程序。对共享资源的修改放在由P(互斥)和V(互斥)保护的关键部分下,这些关键部分代码放在公共库中。该库将由(我自己的)并发应用程序使用 我有三个应用程序,它们将使用库中的公共代码并独立完成它们的工作 my library --------- work_on_shared_resource { P(mutex) get_shared_resource work_with_it V(mutex) } ---

我想在这里分享我的多道程序设计实践经验

昨天我写了一个多道程序。对共享资源的修改放在由P(互斥)和V(互斥)保护的关键部分下,这些关键部分代码放在公共库中。该库将由(我自己的)并发应用程序使用

我有三个应用程序,它们将使用库中的公共代码并独立完成它们的工作

 my library
 ---------
 work_on_shared_resource
 {
  P(mutex)
  get_shared_resource
  work_with_it
  V(mutex)
 }
     ---------

 my application
 -----------
 application1
 {
   *[
      work_on_shared_resource
      do_something_else_non_ctitical
    ]
 }


 application2
 {
   *[
      work_on_shared_resource
      do_something_else_non_ctitical
    ]
 }


 application3
 {
   *[
      work_on_shared_resource
    ]
 }

 *[...] denote a loop.
 ------------
我必须在Linux操作系统上运行应用程序。多年来,我一直在想,操作系统应该公平地安排在他手下运行的所有进程。换句话说,它将给所有进程提供同样好的资源利用率

当前两个应用程序开始工作时,它们运行良好,没有死锁。但是,当第三个应用程序开始运行时,第三个应用程序总是获得资源,但由于它在其非关键区域内不做任何事情,因此当其他任务正在执行其他任务时,它会更频繁地获得共享资源。因此,其他两个应用程序几乎完全停止。当第三份申请被强行终止时,前两份申请恢复了原来的工作

我认为,这是一个饥饿的情况,前两个应用程序必须饥饿

现在我们如何确保公平

现在我开始相信操作系统调度器是无辜和盲目的。这取决于谁赢得了比赛;他得到了最大的CPU和资源

在图书馆的关键章节代码中,我们是否应该尝试确保资源用户的公平性

还是我们应该让申请者通过自由而不是贪婪来确保公平

据我所知,添加代码以确保公共库的公平性将是一项艰巨的任务。另一方面,相信申请也永远无法保证100%的公平性。在使用共享资源工作后只执行很少任务的应用程序将赢得这场竞赛,而在使用共享资源工作后执行大量处理的应用程序将始终处于饥饿状态

在这种情况下,最佳做法是什么?我们在哪里确保公平,如何确保公平

真诚地,

斯里尼瓦斯·纳亚克(Srinivas Nayak)

为了确保平等共享或检测并避免死锁,已经对撤销互斥锁的所有权进行了研究。然而,这真的是杀伤力过大,不值得付出努力,特别是因为它打开了一个全新的蠕虫罐,比如程序在进行某些计算时应该如何运行,并且它失去了对其资源的所有权。这实际上取决于应用程序,以确保其各个线程之间公平竞争,并以不会死锁的方式消耗资源


我应该指出,还有另一种选择,尽管种类略有不同,那就是使用并行编程的消息传递风格。通过消息传递,通信中的同步都是隐式的;不需要显式同步,这有助于避免此类错误。

有人研究撤销互斥锁的所有权,以确保平等共享或检测并避免死锁。然而,这真的是杀伤力过大,不值得付出努力,特别是因为它打开了一个全新的蠕虫罐,比如程序在进行某些计算时应该如何运行,并且它失去了对其资源的所有权。这实际上取决于应用程序,以确保其各个线程之间公平竞争,并以不会死锁的方式消耗资源


我应该指出,还有另一种选择,尽管种类略有不同,那就是使用并行编程的消息传递风格。通过消息传递,通信中的同步都是隐式的;不需要显式同步,这有助于避免此类错误。

出现问题的原因是“应用程序3”进程在解锁互斥锁后继续运行,因此可以立即再次获取互斥锁

您可以实现一个公平队列系统,其中每个线程在阻塞时都添加到队列中,并且队列上的第一个线程在资源可用时总是获取资源。您可以使用条件变量来构建它。这种基于pthreads原语构建的“公平”票证锁可能如下所示:

#include <pthread.h>

typedef struct ticket_lock {
    pthread_cond_t cond;
    pthread_mutex_t mutex;
    unsigned long queue_head, queue_tail;
} ticket_lock_t;

#define TICKET_LOCK_INITIALIZER { PTHREAD_COND_INITIALIZER, PTHREAD_MUTEX_INITIALIZER }

void ticket_lock(ticket_lock_t *ticket)
{
    unsigned long queue_me;

    pthread_mutex_lock(&ticket->mutex);
    queue_me = ticket->queue_tail++;
    while (queue_me != ticket->queue_head)
    {
        pthread_cond_wait(&ticket->cond, &ticket->mutex);
    }
    pthread_mutex_unlock(&ticket->mutex);
}

void ticket_unlock(ticket_lock_t *ticket)
{
    pthread_mutex_lock(&ticket->mutex);
    ticket->queue_head++;
    pthread_cond_broadcast(&ticket->cond);
    pthread_mutex_unlock(&ticket->mutex);
}
#包括
typedef结构票据锁{
pthread_cond_t cond;
pthread_mutex_t mutex;
无符号长队列头、队列尾;
}车票锁;
#定义票据\锁\初始值设定项{PTHREAD\ COND\初始值设定项,PTHREAD\ MUTEX\初始值设定项}
无效票锁(票锁*票)
{
未签名的长队;
pthread_mutex_lock(&ticket->mutex);
queue_me=ticket->queue_tail++;
while(排队我!=车票->排队头)
{
pthread_cond_wait(&ticket->cond,&ticket->mutex);
}
pthread_mutex_unlock(&ticket->mutex);
}
无效车票解锁(车票锁定车票)
{
pthread_mutex_lock(&ticket->mutex);
票证->队列头++;
pthread_cond_广播(&ticket->cond);
pthread_mutex_unlock(&ticket->mutex);
}

出现问题的原因是“应用程序3”进程在解锁互斥锁后继续运行,因此可以立即再次获取互斥锁

您可以实现一个公平队列系统,其中每个线程在阻塞时都添加到队列中,并且队列上的第一个线程在资源可用时总是获取资源。您可以使用条件变量来构建它。这种基于pthreads原语构建的“公平”票证锁可能如下所示:

#include <pthread.h>

typedef struct ticket_lock {
    pthread_cond_t cond;
    pthread_mutex_t mutex;
    unsigned long queue_head, queue_tail;
} ticket_lock_t;

#define TICKET_LOCK_INITIALIZER { PTHREAD_COND_INITIALIZER, PTHREAD_MUTEX_INITIALIZER }

void ticket_lock(ticket_lock_t *ticket)
{
    unsigned long queue_me;

    pthread_mutex_lock(&ticket->mutex);
    queue_me = ticket->queue_tail++;
    while (queue_me != ticket->queue_head)
    {
        pthread_cond_wait(&ticket->cond, &ticket->mutex);
    }
    pthread_mutex_unlock(&ticket->mutex);
}

void ticket_unlock(ticket_lock_t *ticket)
{
    pthread_mutex_lock(&ticket->mutex);
    ticket->queue_head++;
    pthread_cond_broadcast(&ticket->cond);
    pthread_mutex_unlock(&ticket->mutex);
}
#包括
typedef结构票据锁{
pthread_cond_t cond;
pthread_mutex_t mutex;
无符号长队列头、队列尾;
}车票锁;
#定义票据\锁\初始值设定项{PTHREAD\ COND\初始值设定项,PTHREAD\ MUTEX\初始值设定项}
无效票锁(票锁*票)
{
未签名的长队;
pthread_mutex_l