Process 时间戳可以用于具有竞争条件的进程的同步吗?

Process 时间戳可以用于具有竞争条件的进程的同步吗?,process,operating-system,synchronization,Process,Operating System,Synchronization,我想知道当竞争条件发生时,时间戳是否可以用来解决进程同步问题?下面是每个想要进入关键部分的流程的入口和出口部分的算法。入口段采用FCFS先到先得技术,允许进入关键段 interested[N] is shared array of N integers where N is number of processes. // This section executed when process enters critical section. entry_section (

我想知道当竞争条件发生时,时间戳是否可以用来解决进程同步问题?下面是每个想要进入关键部分的流程的入口和出口部分的算法。入口段采用FCFS先到先得技术,允许进入关键段

    interested[N] is shared array of N integers where N is number of processes.

    // This section executed when process enters critical section.
    entry_section (int processNumber) {
        interested [processNumber] = getCurrentTimeStamp ();  // Gets the current timestamp.
        index = findOldestProcessNumber (interested);         // Find the process number with least timestamp.
        while (index != processNumber);
    }

    // This section executed when process leaves critical section.
    exit_section (int processNumber) {
        interested [processNumber] = NULL;
    }
据我所知,该算法满足所有同步条件,即互斥、进度、有界等待和可移植性。那么,我说的对吗


感谢您抽出时间。

您的代码只是一个草图,但很可能不会在所有情况下都有效

如果没有锁且所有函数都使用非原子操作,则无法保证代码将正确执行。它本质上与第一个示例相同,只是您使用的是一个数组,并且假设您不需要原子性,因为每个进程将只访问它自己的元素

让我试着提出一个反例

很少有小的澄清

据我所知,每个进程的省略部分都在循环中运行

while(!processExitCondition)
{
    // some non-critical code
    ...
    // your critical section as in the question
    entry_section (int processNumber) {
        interested [processNumber] = getCurrentTimeStamp ();  // Gets the current timestamp.
        index = findOldestProcessNumber (interested);         // Find the process number with least timestamp.
        while (index != processNumber);
    }

    // This section executed when process leaves critical section.
    exit_section (int processNumber) {
        interested [processNumber] = NULL;
    }
    // more non-critical code
    ...
}
在我看来,调度部分应该忙于等待,不断地获取最旧的进程:

while (findOldestProcessNumber (interested) != processNumber);
否则,所有线程都可以立即挂起在无限while循环中,但第一个线程将执行一次,然后立即挂起

现在,您的调度函数findOldestProcessNumber感兴趣;有一些有限的执行时间,如果我假设存在一个进程外循环!processExitCondition正确,此执行时间可能恰好比关键部分之前或之后的内部代码执行慢。因此,完成的进程可以在findOldestProcessNumber感兴趣时返回到感兴趣的数组中;迭代它,如果getCurrentTimeStamp;是低保真度,比如说几秒钟,你们可以让两个进程同时进入临界区。想象一下,在findOldestProcessNumber中加入长时间睡眠;而这将更容易看到如何发生

您可以说这是一个人工示例,但关键是无法保证进程将如何相互交错,因此您的同步依赖于假设代码的某些部分执行的时间足够大或足够小。这只是利用这些假设来伪造原子操作的一种尝试

你可以想出一些相反的想法使它发挥作用。假设您可以实现getCurrentTimeStamp来为每个调用方返回唯一的时间戳。一个简单的带有硬件的原子计数器可以保证只有一个进程可以增加它,或者通过内部使用原子锁互斥锁,它自己的关键部分,并忙于等待该锁为每个调用进程提供一个不同的系统时钟值,如果您希望将它作为一个实时计数器的话。但是有一个单独的findOldestProcessNumber感兴趣的电话,我发现很难想出一个方法来保证它。我不能说这是不可能的,但它越复杂,你就越有可能只是在隐瞒相互排斥保证的缺失

因此,使用锁互斥体的最简单解决方案是最好的。在您的代码片段中,在关键部分周围添加一个互斥锁,当前的入口和出口代码仅用于先到先得的调度,互斥锁提供互斥保证


如果您想要一个无锁解决方案,您可以使用队列或实现无锁来推动进程,在entry_部分对队列进行编号,然后等待轮到它,尽管看起来很直观。

您的代码只是一个草图,但很可能无法在所有情况下工作

如果没有锁且所有函数都使用非原子操作,则无法保证代码将正确执行。它本质上与第一个示例相同,只是您使用的是一个数组,并且假设您不需要原子性,因为每个进程将只访问它自己的元素

让我试着提出一个反例

很少有小的澄清

据我所知,每个进程的省略部分都在循环中运行

while(!processExitCondition)
{
    // some non-critical code
    ...
    // your critical section as in the question
    entry_section (int processNumber) {
        interested [processNumber] = getCurrentTimeStamp ();  // Gets the current timestamp.
        index = findOldestProcessNumber (interested);         // Find the process number with least timestamp.
        while (index != processNumber);
    }

    // This section executed when process leaves critical section.
    exit_section (int processNumber) {
        interested [processNumber] = NULL;
    }
    // more non-critical code
    ...
}
在我看来,调度部分应该忙于等待,不断地获取最旧的进程:

while (findOldestProcessNumber (interested) != processNumber);
否则,所有线程都可以立即挂起在无限while循环中,但第一个线程将执行一次,然后立即挂起

现在,您的调度函数findOldestProcessNumber感兴趣;有一些有限的执行时间,如果我假设存在一个进程外循环!processExitCondition正确,此执行时间可能恰好比关键部分之前或之后的内部代码执行慢。因此,完成的过程可以回到感兴趣的领域 findOldestProcessNumber感兴趣时之前的数组;迭代它,如果getCurrentTimeStamp;是低保真度,比如说几秒钟,你们可以让两个进程同时进入临界区。想象一下,在findOldestProcessNumber中加入长时间睡眠;而这将更容易看到如何发生

您可以说这是一个人工示例,但关键是无法保证进程将如何相互交错,因此您的同步依赖于假设代码的某些部分执行的时间足够大或足够小。这只是利用这些假设来伪造原子操作的一种尝试

你可以想出一些相反的想法使它发挥作用。假设您可以实现getCurrentTimeStamp来为每个调用方返回唯一的时间戳。一个简单的带有硬件的原子计数器可以保证只有一个进程可以增加它,或者通过内部使用原子锁互斥锁,它自己的关键部分,并忙于等待该锁为每个调用进程提供一个不同的系统时钟值,如果您希望将它作为一个实时计数器的话。但是有一个单独的findOldestProcessNumber感兴趣的电话,我发现很难想出一个方法来保证它。我不能说这是不可能的,但它越复杂,你就越有可能只是在隐瞒相互排斥保证的缺失

因此,使用锁互斥体的最简单解决方案是最好的。在您的代码片段中,在关键部分周围添加一个互斥锁,当前的入口和出口代码仅用于先到先得的调度,互斥锁提供互斥保证


如果您想要一个无锁的解决方案,您可以使用队列或实现一个无锁来推动进程,在entry_部分对队列进行编号,然后等待轮到它,尽管看起来很直观。

这是该方法的两个问题

所有进程都在忙着等待。这意味着,即使流程无法进入关键部分,也无法停止。这意味着操作系统调度器需要不断地调度所有感兴趣的进程,即使它们没有产生有意义的输出。这会影响性能和功耗。 这是最大的一个。不能保证两个进程不会有相同的时间戳。这可能不太可能,但当你们想要保证相互排斥以防止种族状况时,可能性并不是你们想要的。
简而言之,这种方法有两个问题

所有进程都在忙着等待。这意味着,即使流程无法进入关键部分,也无法停止。这意味着操作系统调度器需要不断地调度所有感兴趣的进程,即使它们没有产生有意义的输出。这会影响性能和功耗。 这是最大的一个。不能保证两个进程不会有相同的时间戳。这可能不太可能,但当你们想要保证相互排斥以防止种族状况时,可能性并不是你们想要的。
测试时你发现了什么?@MartinJames我没有用任何语言实现它,但我在想这是否可以实现?@MartinJames有一个很好的解决方案,用于两个进程,即。,Peterson的算法满足问题中提到的所有条件,但我认为这个解决方案也适用于2个以上的过程。为什么有人否决了这个问题?问这样的问题不对吗?@Shiv-我只是想知道,您的流程共享哪些数据?如果两个或多个进程在完全相同的时间戳上使用共享数据,会发生什么情况?如果出于某种原因,两个或多个进程以相同的时间戳开始,会发生什么情况?这可能发生在2Ghz CPU每秒可以执行20亿个周期的情况下。因此,从技术上讲,在同一毫秒内可以发生多个操作。因此,如果您的时间戳只有第二个,那么这个问题将变得最糟糕。您在测试它时发现了什么?@MartinJames我没有用任何语言实现它,但我在想这是否可以实现?@MartinJames有一个很好的解决方案用于两个进程,即。,Peterson的算法满足问题中提到的所有条件,但我认为这个解决方案也适用于2个以上的过程。为什么有人否决了这个问题?问这样的问题不对吗?@Shiv-我只是想知道,您的流程共享哪些数据?如果两个或多个进程在完全相同的时间戳上使用共享数据,会发生什么情况?如果出于某种原因,两个或多个进程以相同的时间戳开始,会发生什么情况?这可能发生在2Ghz CPU每秒可以执行20亿个周期的情况下。因此,从技术上讲,在同一毫秒内可以发生多个操作。因此,如果您的时间戳只有第二个,那么问题将变得最严重。