0

I have an application I've written in C#, although any similar language would apply here.

The application has the job of drawing a graphical scene to a window on a Form in real-time based on data it receives over various UDP and TCP sockets. Each UDP and TCP connection uses its own thread: these threads each modify various objects in memory which in turn modify the graphical display. I also have a user interface thread which is capable of receiving user events (button clicks, etc) which in turn modify those same objects and the display. Finally, I also have many timers that I fire which launch their own threads which modify those same objects and the display.

The objects in memory that are being modified consist of about 15 different classes.

Everything works pretty reliably, but with all of those different classes being modified by different threads, I've had to add a lot of synchronization locks. I've had to look at each class individually to determine which memory might be altered by more than one thread.

It seems very easy in this situation to miss one of those spots: to forget to add synchronization somewhere it's needed.

I'm curious as to whether others would implement this the way I did, or if there's some more elegant way: perhaps somehow putting all of the modification of class A on its own thread or something?

(P.S. I'm deathly afraid of asking a question here after things didn't go so well the first time. But I don't think my query here is super-obvious so I'm hoping you won't either. ;o)

4

1 回答 1

1

我相信对此没有直接的答案。

我帮助其他人更改设计以处理类似情况。最常用的技术之一是引入更好的抽象。

例如,假设您有多个线程需要更新包含用户的地图和另一个包含活动用户的集合,而不是为用户地图和活动用户集设置锁并让您的线程手动获取锁,我会建议引入一个抽象调用 UserRepository,其中包含用户映射和活动用户集。UserRepository 将为其他人提供一些对业务有意义的方法来操作 UserRepository。锁是在 UserRepository 的方法中获取的,而不是由调用者显式获取。

根据我过去的经验,通过像上面提到的示例这样更好的设计,可以大大简化 80% 以上的复杂同步。

还有其他可能的技术。例如,如果更新可以异步进行,那么您可以创建命令对象并放入生产者-消费者队列中,而不是让您的线程直接更新资源,并让专用线程执行更新。

此外,有时使用更少的锁更容易处理。例如,当更新多个资源时,我们可以将更新视为一个整体动作,而不是每个资源都拥有一个锁,并且只使用一个锁来进行线程之间的协调。当然它会增加争用,但有些情况下争用不是一个大问题,而是我们想要可维护性。

我相信还有很多其他方法可以处理类似情况,我只是分享我以前的一些经验(有效:P)

于 2013-01-07T01:49:07.180 回答