积极答复者
线程的同步和类的原子功能,菜鸟问如何使用..

问题
-
//同步类: class Demo { private ShareState _state; public Demo() { } public Demo(ShareState state) { this._state = state; } public virtual void DoTheJob() { //异步方法. for(int i = 0; i < 50000; i++) { //lock(_state) //记住在这里也要同步(一个任务不一定是一个线程). _state.IncreaseState(); } } public static Demo Synchronized(Demo demo) { //同步对象. if(!demo.IsSynchronized) return new SynchronizationDemo(demo); return demo; } public virtual bool IsSynchronized { //异步属性. get { return false; } } private class SynchronizationDemo : Demo { private object syncRoot = new object(); //用于同步的对象. private Demo d; public override bool IsSynchronized { //同步属性. get { return true; } } public override void DoTheJob() { //同步方法. lock(syncRoot) { d.DoTheJob(); } } public SynchronizationDemo(Demo d) { this.d = d; } } } //拥有类原子功能的类: class ShareState { //原子功能. private ShareState _shareState = new ShareState(); //用于锁定线程. private int _state = 0; public int State { get { return _state; } } public int IncreaseState() { lock(_shareState) return ++_state; } } //Call in the Main(): //同步方式: ShareState state = new ShareState(); //用于同步(锁定)的对象. int numTask = 20; Task[] tasks = new Task[numTask]; //任务数组. for(int i = 0; i < tasks.Length; i++) { Demo d = new Demo(state); d = Demo.Synchronized(d); //同步对象. tasks[i] = new Task(d.DoTheJob); tasks[i].Start(); } for(int i = 0; i < tasks.Length; i++) tasks[i].Wait(); Console.Write(state.State);
//在"原子功能"的类中,在行: private ShareState _shareState = new ShareState(); //用于锁定线程. 报异常,StackOverflow...内存溢出了..我觉得是不是递归的问题... 是哪里的问题哈..我的设计..和使用...哪里不对..
答案
-
原因在于这一句:
class ShareState { //原子功能. private ShareState _shareState = new ShareState(); //用于锁定线程.
注意划线部分——把ShareState改为object。
此外值得修改的:
for(int i = 0; i < tasks.Length; i++)tasks[i].Wait();
改为:
Task.WaitAll(tasks);
for语句最好改为(因为Task的Start不一定马上启动,但是i此时已经++了,可能产生同步性问题)。
for (int i = 0; i < tasks.Length; i++) { int j = i; Demo d = new Demo(state); d = Demo.Synchronized(d); //同步对象. tasks[j] = new Task(d.DoTheJob); tasks[j].Start(); }
If you think one reply solves your problem, please mark it as An Answer, if you think someone's reply helps you, please mark it as a Proposed Answer
Help by clicking:
Click here to donate your rice to the poor
Click to Donate
Click to feed Dogs & Cats
Found any spamming-senders? Please report at: Spam Report- 已标记为答案 Min ZhuModerator 2013年7月8日 8:08
全部回复
-
原因在于这一句:
class ShareState { //原子功能. private ShareState _shareState = new ShareState(); //用于锁定线程.
注意划线部分——把ShareState改为object。
此外值得修改的:
for(int i = 0; i < tasks.Length; i++)tasks[i].Wait();
改为:
Task.WaitAll(tasks);
for语句最好改为(因为Task的Start不一定马上启动,但是i此时已经++了,可能产生同步性问题)。
for (int i = 0; i < tasks.Length; i++) { int j = i; Demo d = new Demo(state); d = Demo.Synchronized(d); //同步对象. tasks[j] = new Task(d.DoTheJob); tasks[j].Start(); }
If you think one reply solves your problem, please mark it as An Answer, if you think someone's reply helps you, please mark it as a Proposed Answer
Help by clicking:
Click here to donate your rice to the poor
Click to Donate
Click to feed Dogs & Cats
Found any spamming-senders? Please report at: Spam Report- 已标记为答案 Min ZhuModerator 2013年7月8日 8:08
-
这是 for,好像多一个 j,貌似没有区别吧...因为 i 变化的时候,还是一样赋值给 j的哈..又不是 i++ 和 ++i..
这个怎么感觉真的一样...
最好另外赋值,因为一个Theard不是立即启动,是延时启动的。If you think one reply solves your problem, please mark it as An Answer, if you think someone's reply helps you, please mark it as a Proposed Answer
Help by clicking:
Click here to donate your rice to the poor
Click to Donate
Click to feed Dogs & Cats
Found any spamming-senders? Please report at: Spam Report -
还有那个 object是什么原因哈...我觉得这个才是关键中的关键...因为什么WaitAll哈..改了好多..改到 object就行了...
对,这是我第一句就指出的。
一般lock上锁的对象都是object。
If you think one reply solves your problem, please mark it as An Answer, if you think someone's reply helps you, please mark it as a Proposed Answer
Help by clicking:
Click here to donate your rice to the poor
Click to Donate
Click to feed Dogs & Cats
Found any spamming-senders? Please report at: Spam Report -
我知道你的意思...只是我觉得,在这里多一个变量,感觉不起作用...因为我觉得,在这里我假设它是延迟启动的...但是这貌似不影响的..
tasks[i] = new Task(d.DoTheJob); tasks[i].Start();
就算是延迟..但是它的值还是不变的,不是么...比如,这里赋值为 tasks[1].Start();(这个延迟,还没有启动).然后下一个 tasks[2].Start()开始启动...但是他们的赋值...不会影响到对方的,在内存中只是等待状态而已...对吧...
不是,我现在搜的是,为什么 类型要是 object. 而不能是它的派生类(也就是说为什么不能是它的类型).这个我不懂...想让你帮我解释一下...我想不通...
-
general, avoid locking on a public type, or instances beyond your code's control. The common constructs lock (this), lock (typeof (MyType)), andlock ("myLock") violate this guideline:
-
lock (this) is a problem if the instance can be accessed publicly.
-
lock (typeof (MyType)) is a problem if MyType is publicly accessible.
-
lock("myLock") is a problem because any other code in the process using the same string, will share the same lock.
Best practice is to define a private object to lock on, or a private static object variable to protect data common to all instances.
- 已标记为答案 JcsonSharpenden 2013年6月21日 6:47
- 取消答案标记 ThankfulHeartModerator 2013年6月22日 7:03
-
-
不是这个原因——
因为你一个类中嵌套自身的实例化,譬如这样照样死掉:
namespace Csharp { public class A { private A a = new A(); } public class Test { static void Main(string[] args) { A a = new A(); } } }
自己调用自己,当然死循环啦。
If you think one reply solves your problem, please mark it as An Answer, if you think someone's reply helps you, please mark it as a Proposed Answer
Help by clicking:
Click here to donate your rice to the poor
Click to Donate
Click to feed Dogs & Cats
Found any spamming-senders? Please report at: Spam Report -
怎么没有关系?你试过我代码没有?照样StackOverFlow。
namespace Csharp { public class A { private A a = new A(); } public class Test { static void Main(string[] args) { A a = new A(); } } }
If you think one reply solves your problem, please mark it as An Answer, if you think someone's reply helps you, please mark it as a Proposed Answer
Help by clicking:
Click here to donate your rice to the poor
Click to Donate
Click to feed Dogs & Cats
Found any spamming-senders? Please report at: Spam Report -
你的问题是StackOverFlow,我改成object没有了,说明你多线程共同访问锁定没有问题。唯一的问题只有可能是自身内部实例化自己,导致无限创建对象。
If you think one reply solves your problem, please mark it as An Answer, if you think someone's reply helps you, please mark it as a Proposed Answer
Help by clicking:
Click here to donate your rice to the poor
Click to Donate
Click to feed Dogs & Cats
Found any spamming-senders? Please report at: Spam Report -
你首先尝试我的代码,报同样的错误。
我承认,报同样的错误不一定证明说一定是死循环造成。可是为什么换成object就好了呢?显然证明了一点——那就是你一个类中自己实例化自己,会导致内部不断调用自身构造函数,如此反复生成实体,直到内存耗尽为止。
If you think one reply solves your problem, please mark it as An Answer, if you think someone's reply helps you, please mark it as a Proposed Answer
Help by clicking:
Click here to donate your rice to the poor
Click to Donate
Click to feed Dogs & Cats
Found any spamming-senders? Please report at: Spam Report