让我们做一些假设(为了讨论):
- 我们的进程将是线程——而不是实际的软件进程,两者之间存在差异,这对您的作业可能很重要。
- 白色进程是读者。
- 黑色进程是作家。
- 我们的共同资源是特定的变量。
互斥锁(mutex http://en.wikipedia.org/wiki/Mutual_exclusion):
互斥锁是一种排它锁,它具有二进制状态,要么锁定,要么解锁。您可以锁定它、解锁它或检查它是否已锁定。
线程可以使用互斥锁(互斥锁)相互锁定,就像进程可以使用信号量相互锁定一样。
当您想要保护一个变量不被两个线程同时使用时,您可以为该变量创建一个互斥体并写入每个线程,以便它在尝试使用该变量之前尝试锁定互斥体并在使用完成后解锁它。
这使得任何第一个线程锁定互斥体并阻止任何后续线程,直到第一个线程解锁互斥体,基本上强制所有这些线程排队并按顺序操作该特定变量。
当您只想读取变量而不更改其值时,这有点无效,因为读取相同内容的两个线程不会创建任何冲突或无效数据。然而,两个线程同时写入可能会损坏数据。
读者/写者锁 http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock (RWL):
大多数读/写锁的实现都会使用共享锁和独占锁,但它们公开了一种简单的使用方法:如果你想读,就获取“读锁”,如果你想写,就获取“写锁”。
“读锁”不是独占的,它们允许多个读者在某一特定时间进行读取(无阻塞)。
“写锁”是独占的,只有一个写入者可以在某一特定时间进行写入(无阻塞)。
饥饿:
- 第一步:读取器/写入器锁是当第一个(读取)线程获取变量上的“读取锁”,第二个(写入)线程尝试获取“写入锁”但被阻塞,直到所有读取器完成读取时发生的事件。
- 第二步:在第一个线程完成读取之前,第三个(读取)线程获取变量上的“读锁”;这意味着第二个(写入)线程必须等待第三个线程完成。
重复第二步,直到达到饥饿状态。
避免饥饿Seqlock http://en.wikipedia.org/wiki/Seqlock:
seqlock 是通过一个互斥锁和一些计数器来实现的。它始终允许读取,即使写入者正在写入变量,但它为读取器提供了一种检查数据在读取期间是否已写入的方法,如果是,则可能会损坏,因此读取器必须重新读取数据并再次检查一致性。
“读取和一致性检查”阶段循环运行,直到检查确认数据的一致性,此时读取器可以继续执行其通常的任务。
编写者使用互斥锁来获取独占访问权限,因此他们永远不会重叠操作。
这对于高读低写的情况很有用。如果写入者太多,读取者将不断循环地重新读取数据。
您的具体情况:
如果黑色进程需要能够在它们之间共享资源,而白色进程需要能够在它们之间共享资源,但白色进程不能与黑色进程共享资源,那么解决方案将不是 RWL 或 Seqlock。
Seqlock 算法的变体可能是您的解决方案。