use*_*585 8 java synchronization data-structures
这个问题涉及Java集合 - 特别是Hashtable和Vector - 但也可能适用于其他地方.
我在很多地方都读到了编程接口的好处,我同意100%.例如,在不考虑底层实现的情况下编程到List接口的能力肯定有助于解耦和测试目的.考虑到内部存储结构,随机访问时间等方面的差异,我可以看到ArrayList和LinkedList如何在不同的环境下应用.但是,这两个实现可以在同一个接口下使用...是很棒的.
我似乎无法放置的是某些同步实现(特别是Hashtable和Vector)如何适应这些接口.对我来说,他们似乎不适合这个模型.大多数底层数据结构实现似乎在数据存储方式(LinkedList,Array,排序树等)方面有所不同,而同步则处理可以访问数据的条件(锁定条件).让我们看一个方法返回Map集合的示例:
public Map<String, String> getSomeData();
Run Code Online (Sandbox Code Playgroud)
让我们假设应用程序完全不关心并发性.在这种情况下,我们对该方法通过接口返回的任何实现进行操作......每个人都很高兴.世界是稳定的.
但是,如果应用程序现在需要关注并发前端怎么办?我们现在无法在不考虑底层实现的情况下运行 - Hashtable会很好,但其他实现必须满足.让我们考虑3种情况:
1)在使用集合添加/删除时,使用同步块等强制执行同步.但是,如果返回同步实现(Hashtable),这不会是过度杀伤吗?
2)更改方法签名以返回Hashtable.然而,这将我们与Hashtable实现紧密联系在一起,因此,编程到界面的优势被抛到了窗外.
3)利用并发包并更改方法签名以返回ConcurrentMap接口的实现.对我来说,这似乎是前进的方向.
从本质上讲,似乎某些同步实现在集合框架中有点不合适,因为在对接口进行编程时,同步问题几乎迫使人们考虑底层实现.
我完全忽略了这一点吗?
谢谢.
1)是的,这将是矫枉过正
2)正确,不应该做
3)取决于情况.
事实是,正如您所知,对接口的编程描述了应用程序的功能(而不是它是如何实现的,那是实现)
同步已从后续实现中删除(请记住,Vector和Hastable之前的java 1.2之前是ArrayList和HasMap未同步,但它们都分别实现了List和Map接口),因为它们导致性能下降同步.例如,如果在单个线程中使用向量,则仍然可以在该单个线程中进行同步.
在设计应用程序时必须考虑在多个线程之间共享数据结构.在那里,您将选择将要使用的方法,并且您将选择谁负责保持数据状态清洁.
您可以在此处选择您提到的选项1或3.会有手动同步吗?我们应该使用同步接口吗?我们将支持哪些版本等
例如,如果你选择1,你也可以在你的设计中拒绝某些实现(即矢量)
数据同步不是通过"运气"发生的事情,你必须设计它才能正确发生并且不会导致它解决的问题.
在此设计期间,您应该注意您将使用的选项(实现)和/或底层基础结构.
避免过度同步的最简单方法是使用不可变数据,不要与其他线程共享数据.
与Martin Fowler分配计算的第一定律非常类似:
"因此,我们得到了我的分布式对象设计第一定律:不要分发你的对象."
多线程应用程序的第一定律是:
多线程应用程序的第一定律:不共享您的数据?
:)
最后说明:Collections类提供了某些接口的"同步"版本: