我需要在C中进行一些进程同步.我想使用一个监视器,我已经阅读了很多关于它们的内容.但是我一直无法找到如何在C中实现它.我已经看到它们用Java和其他语言(如C++)完成,但是我无法在C中找到它们.
我查看了K&R,那里没有例子.我浏览了Unix系统编程,通信,并发和线程,但无法在那里找到监视器实现.
这让我来到这里.我在哪里以及如何定义监视器?如何在其余代码中实现它?
/*我在*nix环境中编码*/
假设我创建了一个信号量.如果我分叉一堆子进程,它们还会使用相同的信号量吗?
另外,假设我创建了一个内部和分叉信号量的结构.所有子进程是否仍然使用相同的信号量?如果没有,将结构+信号量存储在共享内存中是否允许子进程使用相同的信号量?
我真的很困惑我的分叉子进程如何使用相同的信号量.
我正在尝试创建一个将由多个进程使用的共享内存.这些进程使用MPI调用(MPI_Send,MPI_Recv)相互通信.
我需要一种机制来控制这个共享内存的访问我昨天添加了一个问题,看看MPI是否提供了任何设施来做到这一点.MPI创建的进程的共享内存访问控制机制,但似乎MPI没有这样的规定.
所以我必须在named semaphore或之间做出选择flock.
对于命名的信号量,如果任何进程在没有调用的情况下突然死亡sem_cloe(),那么该信号量总是保持不变并且可以被看到ll /dev/shm/.这有时会导致死锁(如果我再次运行相同的代码!),因此我正在考虑使用flock.
只想确认是否flock最适合此类操作?
使用有什么缺点flock吗?
还有什么除了named semaphore和flock这里可以用吗?
我在linux下工作.
我正在启动一个公开WCF端点的子进程.如何从子进程向父进程发出信号,表明子进程已完全初始化并且现在可以访问端点?
我想过为此目的使用信号量,但无法弄清楚如何实现所需的信号.
string pipeUri = "net.pipe://localhost/Node0";
ProcessStartInfo startInfo = new ProcessStartInfo("Node.exe", "-uri=" + pipeUri);
Process p = Process.Start(startInfo);
NetNamedPipeBinding binding = new NetNamedPipeBinding();
var channelFactory = new ChannelFactory<INodeController>(binding);
INodeController controller = channelFactory.CreateChannel(new EndpointAddress(pipeUri));
// need some form of signal here to avoid..
controller.Ping() // EndpointNotFoundException!!
Run Code Online (Sandbox Code Playgroud) developer.android.com中的Semaphore类概述看起来非常好 - 对于那些已经熟悉概念和术语的人来说.
我熟悉那里的一些首字母缩略词和其他术语(例如FIFO,锁等),但是对我来说是新的permits,fairness并且barging对我来说是新的.
你能推荐一个很好的在线资源来解释这些概念吗?(我可能会弄清楚许可和公平是什么,但barging在这一点上是未知的).
编辑:收到下面的两个答案后,我意识到我需要刷新信号量(重新获取()术语).我发现以下资源很有用:
注意:在公开集思广益之后,我已经大量编辑了这个问题.然而,所描述的实际算法以及关于它们是否足以避免比赛的问题应该是相同的.
我正在尝试实现信号量,避免glibc错误号12674中描述的竞争条件:
http://sourceware.org/bugzilla/show_bug.cgi?id=12674
基本上,如果你不关心这种破坏的竞争条件,写一个基于futex的信号量的有效方法是:
帖子:
等待:
后期操作的第2步是不安全的.
有两个明显的实现可以避免这个问题,但两者都存在重大问题:
第一种解决方案是不存储服务员计数或标志,并始终在帖子上执行futex唤醒.这显然是安全的,但却违背了futexes的全部目的(在用户空间中保持无竞争的情况).
第二种解决方案不是存储服务员计数,而是在等待争用时让信号量值减少到-1.然后,post操作从-1转换为1并唤醒所有服务员.其中一个成功将信号量值递减为0,如果有剩余,则将值设置为-1,因此下一个帖子将执行另一个唤醒.这个解决方案显然也是安全的,但是当它发布时,它会导致争夺信号量的线程踩踏.
总之,第一种解决方案仅适用于总是争用的信号量,而后者仅适用于通常不超过一名服务员的信号量.一般用途都不可接受.
现在,尝试一个真正的解决方案......
此时,应该注意的是,还有一些其他要求使现实世界的实施变得复杂.后期操作需要是异步信号安全的(因此它基本上不能使用锁),并且需要等待操作以允许信号,超时或线程取消中断.实际上,这意味着后期操作必须能够安全地"退出"它对信号量状态所做的任何更改.我已经掩饰了这些问题,因为我的方法似乎对他们没有任何问题,但他们确实做出了一些其他明显的变化/解决方案,所以任何人建议新方法作为答案都应该意识到这些问题......
我有一个建议的解决方案,但我不确定它是否会受到新的(可能更糟)的竞争条件的影响.我将在这里描述它,我希望一些并发神(或者至少是半神人)可能有善意去审查它的正确性.
我的方法是上面描述的第二个"坏"解决方案和原始方法(在glibc错误报告中描述的竞争)的混合.它使用服务器计数和服务器标志(-1存储在信号量值中).
等待操作的关键更改是,只要有服务员(预先存在的服务员计数或本身作为新的服务员),它就会在信号量值中存储-1而不是0.
等待:
对post操作的关键更改是它在递增信号量值之前执行对服务器计数的读取,而不是之后:
帖子:
步骤4中的比较和交换提供了服务员计数仍然正确的一些安全性,但仍然存在ABA竞争 - 在步骤1和4之间,其他线程可能执行等待和后续操作,使信号量值保持不变作为其初始值.
在查找此算法可能无法唤醒服务器的情况时,我们只需考虑初始服务器计数读取为0且读取的信号量值不为-1的情况.此外,如果信号量值为正并且没有预先存在的服务员,则当前帖子不对任何唤醒负责,因此这种情况也不感兴趣.我们还在研究等待操作以零信号量值和零等待计数开始的情况.在这种情况下,为了不具有竞争条件,在步骤2和4之间发生的导致新服务员的任何事件必须改变信号量值,以便步骤4中的比较和交换失败.显然,任何单个插入的帖子或等待都将改变信号量值(分别为1或-1),因此更具体地说,关注的情况是导致信号量值为0但存在服务员的操作序列.
我认为由于等待操作中遵循的程序不会发生这种情况,但我并没有100%相信自己.
最后,这里有一些比赛的例子,如果你削弱了我的算法,为了确定它正在做什么的动机,如果不清楚的话.
失败1:使用纯等待计数,信号量值中没有-1标志.琐碎的比赛看起来像:
失败2:使用服务器计数并让新服务员将信号量值设置为-1,但是等待成功时简单地减少信号量值(如果其他线程仍在等待,则不将其设置为-1):
class Program
{
static IEnumerable<site> list = Enumerable.Range(1, 10).Select(i => new site(i.ToString()));
static void Main(string[] args)
{
startup();
Console.ReadKey();
}
static public void startup()
{
router.cts = new CancellationTokenSource();
foreach (var s in list)
{
update(s);
}
}
async static public void update(site s)
{
try
{
while (true)
{
await s.Refresh();
if (site.count % 4 == 0)
{
Console.WriteLine("Reseting Queue");
router.cts.Cancel();
}
}
}
catch (OperationCanceledException)
{
Console.WriteLine("Canceled");
startup();
}
}
}
class router
{
public static SemaphoreSlim ss …Run Code Online (Sandbox Code Playgroud) 这是Can C++ 11的后续条件condition_variables用于同步进程?.
std :: condition_variable对象可以用作计数信号量吗?
Methinks不是因为对象似乎绑定到std :: mutex,这意味着它只能用作二进制信号量.我在网上看过,包括这里,这里和这里,但是找不到使用这些对象作为计数信号量的参考或示例.
这是一项任务,我被要求在Ada中实现一个Semaphore,如下所述.
但是我已经实现了Semaphore.adb并且在producerconsumer_sem.adb我创建的中调用了这个信号量 .
我得到一些输出,如下.
我不确定我的信号量初始化是否正确S: CountingSemaphore(1,1);.
我不知道我在哪里调用S.wait,S.Signal现在我随机调用S.wait生产者之前把物品放在缓冲区X := I;和S.Signal之后X := I;.这是正确的方法吗?
生产者 - 消费者问题该计划
producerconsumer.adb实施了生产者 - 消费者问题的不可靠实施,其中数据可能会丢失.在下文中,您将使用三种不同的通信机制来实现生产者 - 消费者问题的可靠实施.信号
Ada语言不直接为信号量提供库函数.但是,信号量可以通过受保护对象实现.在文件Semaphores.ads中创建包规范Semaphore,并在文件
Semaphores.adb中创建实现计数信号量的相应包体.程序包的骨架可在课程页面上找到.使用信号量包可以可靠地实现生产者 - 消费者问题.修改文件
producerconsumer.adb并将最终代码保存为producerconsumer_sem.adb.为了使用信号量包,它应安装在同一目录中producerconsumer_sem.adb.然后可以访问它
with Semaphores;use Semaphores;
输出:
OutPut: 1 1 1 2 2 3 4 4 5 6 6 7 7 8 9 9 9 10 11 11 11 12 12 …
尝试使用信号量来控制异步请求,以控制对目标主机的请求,但是出现以下错误(我已经假设这asycio.sleep()是错误的),即我实际上并未处于睡眠状态。我怎样才能解决这个问题?我想在每个目标网址的请求中添加延迟。
错误:
RuntimeWarning: coroutine 'sleep' was never awaited
Coroutine created at (most recent call last)
File "sephora_scraper.py", line 71, in <module>
loop.run_until_complete(main())
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 571, in run_until_complete
self.run_forever()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 539, in run_forever
self._run_once()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 1767, in _run_once
handle._run()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/events.py", line 88, in _run
self._context.run(self._callback, *self._args)
File "makeup.py", line 26, in get_html
asyncio.sleep(delay)
asyncio.sleep(delay)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
Run Code Online (Sandbox Code Playgroud)
码:
import sys
import time
import asyncio
import aiohttp
async …Run Code Online (Sandbox Code Playgroud)