我对并发系统很陌生,所以我有点困在这里。
正在处理的某些资源
public class Resource
{
public int Capacity { get; set; } = 1000;
}
消费者
public class Consumer
{
private readonly int _sleep;
public Consumer(int sleep)
{
_sleep = sleep;
}
public void ConsumeResource(Resource resource)
{
var capture = resource.Capacity;
Thread.Sleep(_sleep); // some calsulations and stuff
if (resource.Capacity != capture)
throw new SystemException("Something went wrong");
resource.Capacity -= 1;
}
}
public class ResourceManager
{
private readonly List<Consumer> _consumers;
private readonly Resource _resource;
public ResourceManager(List<Consumer> consumers)
{
_consumers = consumers;
_resource = new Resource();
}
public void Process()
{
Parallel.For(0, _consumers.Count, i =>
{
var consumer = _consumers[i];
consumer.ConsumeResource(_resource);
});
}
}
如您所见,消费者依赖于资源状态。如果使用以下代码运行此模拟
static void Main(string[] args)
{
var consumers = new List<Consumer>
{
new Consumer(1000),
new Consumer(900),
new Consumer(800),
new Consumer(700),
new Consumer(600),
};
var resourceManager = new ResourceManager(consumers);
resourceManager.Process();
}
我想不出任何其他的例子,它缺少一些细节。
-
它不会放弃使代码并发的所有努力。
-
第二,在实际应用中这个问题是非常罕见的,所以我可以
牺牲一些表演。
我猜这个问题可以用适当的方法解决
lock
s、 但我没把它们放对。
s、 它防止从不同的线程同时调用锁定的代码。放置
锁
Consumer::ConsumeResource
不会有帮助,就像放在里面一样
Resource::Capacity
塞特。我需要在使用者处理资源时以某种方式锁定对资源的修改。
我希望我能有效地解释我的问题。这对我来说是全新的,所以如果需要的话,我会尽量让事情更具体。
经过深思熟虑,我想出了一个有点草率的解决办法。
我决定使用comsumer的id锁定消费者的资源属性,并手动等待下一个消费者的轮到:
public class Resource
{
private int Capacity { get; set; } = 1000;
private Guid? _currentConsumer;
public int GetCapacity(Guid? id)
{
while (id.HasValue && _currentConsumer.HasValue && id != _currentConsumer)
{
Thread.Sleep(5);
}
_currentConsumer = id;
return Capacity;
}
public void SetCapacity(int cap, Guid id)
{
if (_currentConsumer.HasValue && id != _currentConsumer)
return;
Capacity = cap;
_currentConsumer = null;
}
}
public class Consumer
{
private readonly int _sleep;
private Guid _id = Guid.NewGuid();
public Consumer(int sleep)
{
_sleep = sleep;
}
public void ConsumeResource(Resource resource)
{
var capture = resource.GetCapacity(_id);
Thread.Sleep(_sleep); // some calsulations and stuff
if (resource.GetCapacity(_id) != capture)
throw new SystemException("Something went wrong");
resource.SetCapacity(resource.GetCapacity(_id) - 1, _id);
}
}
锁
s。