c-将一些线程的资源分配给全局资源,这样就没有并发(只使用互斥)



问题摘要如下:给定大小为N和M的全局资源线程,其资源大小为Xi(i=1,M(,同步线程,以便分配线程,完成其任务,然后将其释放。

主要问题是没有可用的资源,线程必须等到有足够的内存。我曾试图用while语句"阻止"它,但我意识到两个线程可以通过while循环,第一个要分配的线程可以更改全局资源,使第二个线程没有足够的空间,但它已经通过了条件部分。

//piece of pseudocode
...
int MAXRES = 100;
// in thread function
{
while (thread_res  > MAXRES);
lock();
allocate_res(); // MAXRES-=thread_res;
unlock();
// do own stuff
lock()
deallocate(); // MAXRES +=thread_res;
unlock();
}

要制作一个健壮的解决方案,您需要更多的东西。正如您所指出的,您需要一种方法来等待条件"有足够的资源可供我使用",而一个合适的互斥体没有这样的机制。无论如何,您可能希望将其隐藏在分配器中,因此主线线程代码看起来像:

....
n = Allocate()
do stuff
Release(n)
....

并处理争论:

int navail = N;
int Acquire(int n) {
lock();
while (n < navail) {
unlock();
lock();
}
navail -= n;
unlock();
return n;
}
void Release(int n) {
lock();
navail += n;
unlock();
}

但是,这样一个旋转等待系统可能会因为优先级而失败——如果优先级最高的线程正在旋转,那么尝试Release的线程可能无法运行。纺纱不是很优雅,而且浪费能源。你可以在旋转中小睡一会儿,但如果你睡得太短,就会浪费能量,睡得太久,还会增加延迟。

你真的想要一个像信号量或condvars这样的信号原语,而不是一个锁定原语。有了信号灯,它看起来可能会令人印象深刻地像:

Semaphore *sem;
int Acquire(int n) {
senter(sem, n);
return n;
}
int Release(int n) {
sleave(sem, n);
return n;
}
void init(int N) {
sem = screate(N);
}

更新:修订为使用System V信号量,它提供了对信号量值指定任意"checkout"one_answers"checkin"的能力。总体逻辑相同。

免责声明:我已经好几年没有使用System V了,在使用之前进行了测试,以防我错过了一些细节。

int semid ;
// Call from main
do_init() {
shmkey = ftok(...) ;
semid = shmget(shmkey, 1, ...) ;
// Setup 100 as max resources.
struct sembuf so ;
so.sem_num = 0 ;
so.sem_op = 100 ;
so.sem_flg = 0 ;
semop(semid, &so, 1) ;
}
// Thread work
do_thread_work() {
int N = <number of resources>
struct sembuf so ;
so.sem_num = 0;
so.sem_op = -N ;   
so.sem_flg = 0 ;
semop(semid, &so, 1) ;
... Do thread work
// Return resources
so.sem_op = +N ;
semop(semid, &so, 1) ;
}

依据:https://pubs.opengroup.org/onlinepubs/009695399/functions/semop.html,这将导致多个项目的原子签出。

注意:。。。作为与IPC_NOWAIT和SEM_UNDO相关的部分,与本例无关。

  • 如果sem_op是负整数,并且调用进程具有更改权限,则将发生以下情况之一:

    • 如果semval(请参阅(大于或等于sem_op的绝对值,则从semval中减去sem_op。。。

    • 。。。

    • 如果semval小于sem_op…的绝对值。。。,semop((将增加与指定信号量关联的semncnt,并暂停调用线程的执行,直到出现以下条件之一:

      • semval的值变得大于或等于sem_op的绝对值。当这种情况发生时,与指定信号量相关的semncnt的值应递减,sem_op的绝对值应从semval中减去

最新更新