none
请问Remoting的线程安全性问题 RRS feed

  • 问题

  • 1、请问用Remoting实现的SAO Singleton对象被多客户端调用时是否需要考虑线程安全问题?也就是说在服务器上的这个对象是否要实现成线程安全的?

    2、服务器端SAO Singleton对象的代理是否可以处理多客户的“同时”请求?(这个我想应该是肯定的吧)

    3、客户端的代理是否可以被客户端的多个线程同时访问?也就是说我客户端的多个线程同时调用SAO Singleton对象的方法时,是否会造成代理工作不正常?



    LHL
    2011年6月22日 1:45

答案

  • 其实您的问题与 Remoting 无关,只要涉及到多线程,就一定要考虑线程安全,不管用不用 Remoting。

    首先,Singleton 对象是 Immutable 的吗?也就是,所有的属性和方法是否只是读数据?如果都是只读,那么基本上不用管线程安全问题,注意在读的时候,特别是有 foreach 的时候不要有 lock。

    如果有读有写,那么就要考虑线程安全了,服务器上的代码一定要实现为线程安全的,特别是,有返回什么 List 啊,Dictionary 啊什么的,.NET 中的所有 System.Collections 类型 (不包括 System.Collections.Concurrent) 全部都是非线程安全的,然后如果有写操作时注意使用 ReaderWriterSlim 或者 lock,具体怎么实现我就不多说了。

    对于您的三个问题。

    1、一定会遇到线程安全问题
    2、可以,任何对象都可以“同时”,但需要自己考虑线程同步
    3、可以,但不建议,最好是每个线程为 Remoting 服务器生成单独的客户端 Proxy,否则可能遇到跨域 (Cross AppDomain) 的问题。特别是您的线程不在同一个 AppDomain 时。。。


    Mark Zhou
    • 已标记为答案 lhlzhxh 2011年6月26日 14:39
    2011年6月22日 7:32

全部回复

  • 其实您的问题与 Remoting 无关,只要涉及到多线程,就一定要考虑线程安全,不管用不用 Remoting。

    首先,Singleton 对象是 Immutable 的吗?也就是,所有的属性和方法是否只是读数据?如果都是只读,那么基本上不用管线程安全问题,注意在读的时候,特别是有 foreach 的时候不要有 lock。

    如果有读有写,那么就要考虑线程安全了,服务器上的代码一定要实现为线程安全的,特别是,有返回什么 List 啊,Dictionary 啊什么的,.NET 中的所有 System.Collections 类型 (不包括 System.Collections.Concurrent) 全部都是非线程安全的,然后如果有写操作时注意使用 ReaderWriterSlim 或者 lock,具体怎么实现我就不多说了。

    对于您的三个问题。

    1、一定会遇到线程安全问题
    2、可以,任何对象都可以“同时”,但需要自己考虑线程同步
    3、可以,但不建议,最好是每个线程为 Remoting 服务器生成单独的客户端 Proxy,否则可能遇到跨域 (Cross AppDomain) 的问题。特别是您的线程不在同一个 AppDomain 时。。。


    Mark Zhou
    • 已标记为答案 lhlzhxh 2011年6月26日 14:39
    2011年6月22日 7:32
  • 谢谢!

    我问的第一个问题其实是想知道服务器端会不会将请求排队,然后一个一个处理,这样就不需要线程安全了。看来不会,效率太低。

    第二个问题看来也是不言而喻,作为一个服务器肯定要能同时处理多个客户端的请求。

    第三个问题我是想知道一个多线程的客户端其中一个线程调用GetObject获得Singleton对象代理的引用后,可不可以将这个引用交给多个线程同时调用对象的方法。通过您的回答我知道是可以的,但是不建议,不建议的原因我还不太理解(我是个C++程序员还不太了解AppDomain的概念),不过请问“最好是每个线程为 Remoting 服务器生成单独的客户端 Proxy”是不是指每个线程都调用一下GetObject来获得对象呢?

     


    LHL
    2011年6月23日 3:27
  • 我的建议是对于每个独立线程,都用 Activator.GetObject() 一次以便获取 Singleton 对象的本地 Proxy 实例。

    跨域的问题一般不会出现,因为一般的程序集不会有多个 AppDomain,但是,如果一旦程序集中包含多个 AppDomain 在代理 MarshalByRefObject 的时候就可能出现跨域问题,有时候可能收到线程无法访问非改线程创建的对象的错误。


    Mark Zhou
    2011年6月23日 9:07