C 如何允许某些线程在锁定互斥锁时具有优先级使用PTHREADS

C 如何允许某些线程在锁定互斥锁时具有优先级使用PTHREADS,c,linux,multithreading,pthreads,C,Linux,Multithreading,Pthreads,假设以下代码由10个线程执行 pthread_mutex_lock(&lock) Some trivial code pthread_mutex_unlock(&lock) 为了便于解释,假设螺纹为T1、T2、T3……T10。 我的要求是,只要T1或T2或T3(即T1、T2或T3中的任何一个)正在等待获取锁,其他线程i.t T4、T5、T6…..T10就不应该能够获取锁,即T1、T2和T3应该优先于其他线程获取锁 我想这可以通过增加线程T1、T2和T3的优先级来实现 i、 这是

假设以下代码由10个线程执行

pthread_mutex_lock(&lock)
Some trivial code
pthread_mutex_unlock(&lock)
为了便于解释,假设螺纹为T1、T2、T3……T10。 我的要求是,只要T1或T2或T3(即T1、T2或T3中的任何一个)正在等待获取锁,其他线程i.t T4、T5、T6…..T10就不应该能够获取锁,即T1、T2和T3应该优先于其他线程获取锁

我想这可以通过增加线程T1、T2和T3的优先级来实现

i、 这是伪代码

if this thread is T1 or T2 or T3
increase its priority 
pthread_mutex_lock(&lock)
Some trivial code
pthread_mutex_unlock(&lock)
if this thread is T1 or T2 or T3 decrease it priority to normal
请注意,我想要一个适用于Linux平台的解决方案,并且应该使用pthreads。我真的不在乎任何其他平台。

还要注意的是,我并不想让这3个线程成为实时线程,我希望它们展示它们的解除行为(调度和优先级),除了在上面提到的一小段代码中,我希望它们在获取锁时始终具有优先级

我已经阅读了一些关于Linux中的调度策略和调度优先级的手册页,但无法真正理解:(

这行得通吗?你能帮我提供完成上述任务所需的pthreadapi吗

问候
另一方面,您可能只需要引入另一个用于更高优先级线程的锁。考虑下面的伪代码(我不熟悉pthOrthic语义,但我相信这并不难将代码映射到所需的调用)

编辑(thanx Joseph)

引入exec信号量设置为3(高优先级线程数) 请注意,
pend(exec,3);
意味着此pend将休眠,直到所有3个插槽都可用,并将消耗所有插槽



//init
exec = semaphore(3,3);

//========================

if this is NOT thread (t1,t2,t3)
    lock(low_prio);
    sem_pend(exec,3);
else
    sem_pend(exec,1);
lock(high_prio);
//...
unlock(high_prio);
if this is NOT thread (t1,t2,t3)
    sem_release(exec,3);
    sleep(0); //yield();  //ensures that sem_pend(exec,1) is executed
    unlock(low_prio);
else
    sem_release(exec,1);

据我所知,您真正能够保证这一点的唯一方法是自己编写一个这样工作的锁。然而,这表明,如果线程优先级和优先级继承适用于您的用例,那么使用线程优先级和优先级继承无疑是值得考虑的

要自己实现它,您需要条件变量和等待的低/高优先级线程数

就您需要的概念和API而言,它与实现读/写锁相对类似(但是您需要的语义显然是完全不同的-但是如果您了解r/w锁是如何工作的,您将了解如何实现您想要的)

您可以在此处看到读写锁的实现:

在低优先级线程中,您需要等待高优先级线程完成,就像读卡器等待写入器完成一样

(这本书上面的代码取自它,也是一本很棒的posix线程书,顺便说一句,)

(前两次尝试都有bug,请跳到EDIT2)

也许这样行吗

if NOT this thread is T1 or T2 or T3
    pthread_mutex_lock(&lock1) // see note below
    pthread_mutex_lock(&lock2)
    Some trivial code
    pthread_mutex_unlock(&lock2)
    pthread_mutex_unlock(&lock1)
else
    pthread_mutex_lock(&lock2)
    Some trivial code
    pthread_mutex_unlock(&lock2)        
end if
理由: 有些线程将竞争两个锁,因此优先级较低;有些线程将只竞争一个锁,因此优先级较高。 尽管如此,差异可能很小,然后解决方案将是在获取第一个锁和尝试为高优先级线程提供第二个锁之间引入一些延迟,在这段时间内,高优先级线程将有机会获得锁2。
(免责声明:说到这个,我是个新手)

编辑: 另一种尝试/方法

if NOT (this thread is T1 or T2 or T3)  
    pthread_mutex_lock(&lock1)
    if pthread_mutex_trylock(&lock2) == 0  // low priority threads will not get queued
        Some trivial code
        pthread_mutex_unlock(&lock2)
    end if
    pthread_mutex_unlock(&lock1)
else 
    if (this thread is T1 or T2 or T3)
        pthread_mutex_lock(&lock2)
        Some trivial code
        pthread_mutex_unlock(&lock2)        
    end if
end if
编辑2:又一次尝试(尝试在这里学习)


要用pthread实现这一点,您需要N个列表,每个线程一个优先级。这些列表将包含指向线程pthread cond变量的指针

原理图未测试元代码:

/* the main lock */
pthread_mutex_t TheLock = PTHREAD_MUTEX_INITIALIZER;

/* service structures: prio lists and the lock for them */
pthread_mutex_t prio_list_guard = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t *prio_lists[MY_MAX_PRIO][MY_MAX_THREAD]; /* 0 == highest prio */

/* lock */
void
prio_lock(int myprio)
{
    pthread_cond_t x;

    pthread_mutex_lock( &prio_list_guard );

    if (0 == pthread_mutex_trylock( &TheLock )) {
        pthread_mutex_unlock( &prio_list_guard );
        return 0;
    }

    pthread_cond_init( &x, 0 );
    LIST_ADD( prio_lists[myprio], &x )

    while(1)    /* handle spurious wake-ups */
    {
        pthread_cond_wait( &prio_list_guard, &x );
        if (0 == pthread_mutex_trylock( &TheLock )) 
        {
            LIST_REMOVE( prio_lists[myprio], &x );
            pthread_mutex_unlock( &prio_list_guard );
            return 0;
        }
    }
}

/* unlock */
void
prio_unlock()
{
    int i;
    pthread_cond_t *p;

    pthread_mutex_lock( &prio_list_guard );

    for (i=0; i<MY_MAX_PRIO; i++)
    {
        if ((p = LIST_GETFIRST( prio_lists[i] )))
        {
            pthread_cond_signal( p );
            break;
        }
    }

    pthread_mutex_unlock( &TheLock );

    pthread_mutex_unlock( &prio_list_guard );
}
/*主锁*/
pthread\u mutex\u t TheLock=pthread\u mutex\u初始值设定项;
/*服务结构:prio列表及其锁*/
pthread\u mutex\u t prio\u list\u guard=pthread\u mutex\u初始值设定项;
pthread_cond_t*prio_列出[MY_MAX_prio][MY_MAX_THREAD];/*0==最高优先级*/
/*锁*/
无效的
prio_锁(国际myprio)
{
pthread_cond_t x;
pthread_mutex_lock(&prio_list_guard);
if(0==pthread\u mutex\u trylock(&TheLock)){
pthread_mutex_unlock(&prio_list_guard);
返回0;
}
pthread_cond_init(&x,0);
列表添加(优先级列表[myprio],&x)
而(1)/*处理虚假唤醒*/
{
pthread\u cond\u wait(&prio\u list\u guard,&x);
if(0==pthread\u mutex\u trylock(&TheLock))
{
列表删除(优先级列表[myprio],&x);
pthread_mutex_unlock(&prio_list_guard);
返回0;
}
}
}
/*解锁*/
无效的
prio_解锁()
{
int i;
pthread_cond_t*p;
pthread_mutex_lock(&prio_list_guard);

对于(i=0;i这是我的实现。低优先级线程使用
prio\u lock\u Low()
prio\u unlock\u Low()
来锁定和解锁,高优先级线程使用
prio\u lock\u high()
prio\u unlock\u high()

设计非常简单。高优先级线程保存在关键部分互斥体
->cs_mutex
,低优先级线程保存在条件变量。条件变量互斥体仅保存在对共享变量的更新和条件变量的信令周围

#include <pthread.h>

typedef struct prio_lock {
    pthread_cond_t cond;
    pthread_mutex_t cv_mutex; /* Condition variable mutex */
    pthread_mutex_t cs_mutex; /* Critical section mutex */
    unsigned long high_waiters;
} prio_lock_t;

#define PRIO_LOCK_INITIALIZER { PTHREAD_COND_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER }

void prio_lock_low(prio_lock_t *prio_lock)
{
    pthread_mutex_lock(&prio_lock->cv_mutex);
    while (prio_lock->high_waiters || pthread_mutex_trylock(&prio_lock->cs_mutex))
    {
        pthread_cond_wait(&prio_lock->cond, &prio_lock->cv_mutex);
    }
    pthread_mutex_unlock(&prio_lock->cv_mutex);
}

void prio_unlock_low(prio_lock_t *prio_lock)
{
    pthread_mutex_unlock(&prio_lock->cs_mutex);

    pthread_mutex_lock(&prio_lock->cv_mutex);
    if (!prio_lock->high_waiters)
        pthread_cond_signal(&prio_lock->cond);
    pthread_mutex_unlock(&prio_lock->cv_mutex);
}

void prio_lock_high(prio_lock_t *prio_lock)
{
    pthread_mutex_lock(&prio_lock->cv_mutex);
    prio_lock->high_waiters++;
    pthread_mutex_unlock(&prio_lock->cv_mutex);

    pthread_mutex_lock(&prio_lock->cs_mutex);
}

void prio_unlock_high(prio_lock_t *prio_lock)
{
    pthread_mutex_unlock(&prio_lock->cs_mutex);

    pthread_mutex_lock(&prio_lock->cv_mutex);
    prio_lock->high_waiters--;
    if (!prio_lock->high_waiters)
        pthread_cond_signal(&prio_lock->cond);
    pthread_mutex_unlock(&prio_lock->cv_mutex);
}
#包括
类型定义结构优先锁{
pthread_cond_t cond;
pthread_mutex_t cv_mutex;/*条件变量mutex*/
pthread_mutex_t cs_mutex;/*临界段互斥*/
没有签名的高个子侍者;
}优先锁;
#定义PRIO_LOCK_初始值设定项{PTHREAD_COND_初始值设定项,PTHREAD_MUTEX_初始值设定项,PTHREAD_MUTEX_初始值设定项}
无效优先级锁定低(优先级锁定*优先级锁定)
{
pthread_mutex_lock(&prio_lock->cv_mutex);
while(prio_lock->high_waiters | | | pthread_mutex_trylock(&prio_lock->cs_mutex))
{
pthread_cond_wait(&prio_lock->cond,&prio_lock->cv_mutex);
}
pthread_mutex_unlock(&prio_lock->cv_mutex);
}
无效优先解锁低(优先锁定*优先锁定)
{
pthread_mutex_unlock(&prio_lock->cs_mutex);
pthread\u mutex\u lock(&prio\u lock->cv\u mute)
#include <pthread.h>

typedef struct prio_lock {
    pthread_cond_t cond;
    pthread_mutex_t cv_mutex; /* Condition variable mutex */
    pthread_mutex_t cs_mutex; /* Critical section mutex */
    unsigned long high_waiters;
} prio_lock_t;

#define PRIO_LOCK_INITIALIZER { PTHREAD_COND_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER }

void prio_lock_low(prio_lock_t *prio_lock)
{
    pthread_mutex_lock(&prio_lock->cv_mutex);
    while (prio_lock->high_waiters || pthread_mutex_trylock(&prio_lock->cs_mutex))
    {
        pthread_cond_wait(&prio_lock->cond, &prio_lock->cv_mutex);
    }
    pthread_mutex_unlock(&prio_lock->cv_mutex);
}

void prio_unlock_low(prio_lock_t *prio_lock)
{
    pthread_mutex_unlock(&prio_lock->cs_mutex);

    pthread_mutex_lock(&prio_lock->cv_mutex);
    if (!prio_lock->high_waiters)
        pthread_cond_signal(&prio_lock->cond);
    pthread_mutex_unlock(&prio_lock->cv_mutex);
}

void prio_lock_high(prio_lock_t *prio_lock)
{
    pthread_mutex_lock(&prio_lock->cv_mutex);
    prio_lock->high_waiters++;
    pthread_mutex_unlock(&prio_lock->cv_mutex);

    pthread_mutex_lock(&prio_lock->cs_mutex);
}

void prio_unlock_high(prio_lock_t *prio_lock)
{
    pthread_mutex_unlock(&prio_lock->cs_mutex);

    pthread_mutex_lock(&prio_lock->cv_mutex);
    prio_lock->high_waiters--;
    if (!prio_lock->high_waiters)
        pthread_cond_signal(&prio_lock->cond);
    pthread_mutex_unlock(&prio_lock->cv_mutex);
}