代码示例1:
namespace DummyNameSpace
{
public interface IViewModel<T>
{
T DataModelObject { get; set; }
string Name { get; set; }
}
public class SomeDataModelObject
{
public string SomeProperty { get; set; }
}
public class ViewModelInstance : IViewModel<SomeDataModelObject> //There will be various ViewModels that implement IViewModel, all with different 'T' types.
{
//Some properties, commands, etc.
}
public class TheMainViewModel //won't implement IViewModel, as this will be used to control all the various other viewmodels.
{
public void MethodBeingCalled(object viewmodelinstance)
{
Type type = viewmodelinstance.GetType();
var x = (viewmodelinstance as IViewModel<type>).DataModelObject = null; //Will do other things here.
}
}
}
代码示例2:
class Test {
MyObj myObj = new MyObj();
public void test() {
// doing my other stuff
synchronized (myObj) {
// accessing myObj
}
}
}
代码示例3:
class Test {
MyObj myObj = new MyObj();
public void test() {
synchronized (myObj) {
// doing my other stuff
// accessing myObj
}
}
}
我希望在上面的代码段中保持线程安全 myObj 。那么以上代码中的哪一个是更优选的,为什么呢?
答案 0 :(得分:3)
代码示例1是合适的。 因为持有对象的锁定然后做一些其他的东西是不合适的。
答案 1 :(得分:1)
根据我在开源项目中看到的代码,第一个代码示例更好,因为当您不再需要对象时,您将其释放,以便其他线程可以访问它。
答案 2 :(得分:1)
您的所有示例都没有包含足够的信息。
数据在哪里?什么是不变量?何时/何处/线程如何访问数据?
“线程安全”在没有数据的情况下毫无意义。有状态类的文档通常会提供有关其方法如何推进实例状态的保证。 “线程安全”意味着即使许多线程调用这些方法,也会满足这些保证。但是如果这个类没有状态,或者没有这样的保证,那么“线程安全”就没有任何意义。
P.S。:代码样本1比其他代码具有一个重要优势:互斥体(即synchronized
块)更小。根据经验,您希望您的互斥锁尽可能小。如果“我的其他东西”不关心受互斥锁保护的数据,那么它应该不会发生在互斥锁中,因为这会阻止其他线程访问数据,并且它会阻止它们没有用的原因。
PPS:@ Ordous评论的+1:无法知道某个对象的状态是否是线程安全的,除非你能看到每个代码块可以修改或检查状态。由于您的示例中myObj
不是private
,因此我们必须假设其他地方的代码可以修改或检查其状态。由于我们无法看到该代码,因此我们必须假设myObj
不线程安全。
答案 3 :(得分:1)
对整个方法进行锁定(如果时间很长)非常昂贵。它不仅可以阻止整个威胁,还可以阻止不需要同步的代码。其次,有时您可能不会使用rsautl
,在这种情况下,示例2和3会很糟糕。
简短:仅同步块的一部分,使用对象。您还可以在对象上使用rsautl
来检查它的值,而不使用同步块。请记住锁定可能代价高昂。
但是当你的方法足够短,或只包含myObj的代码时,那么使整个方法同步是一个很好的解决方案。
omyObj
请看这个singleton示例。