none
线程的同步和类的原子功能,菜鸟问如何使用.. RRS feed

  • 问题

  • //同步类:
    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...内存溢出了..我觉得是不是递归的问题...
    是哪里的问题哈..我的设计..和使用...哪里不对..
    


    2013年6月20日 11:29

答案

  • 原因在于这一句:

      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 = 0i < tasks.Lengthi++)
                {
                    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

    2013年6月20日 12:23
    版主

全部回复

  • 原因在于这一句:

      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 = 0i < tasks.Lengthi++)
                {
                    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

    2013年6月20日 12:23
    版主
  • 这是 for,好像多一个 j,貌似没有区别吧...因为 i 变化的时候,还是一样赋值给 j的哈..又不是 i++ 和 ++i..

    这个怎么感觉真的一样...

    2013年6月20日 15:52
  • 还有那个 object是什么原因哈...我觉得这个才是关键中的关键...因为什么WaitAll哈..改了好多..改到 object就行了...
    2013年6月20日 15:56
  • 这是 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

    2013年6月21日 1:28
    版主
  • 还有那个 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

    2013年6月21日 1:33
    版主
  • 我知道你的意思...只是我觉得,在这里多一个变量,感觉不起作用...因为我觉得,在这里我假设它是延迟启动的...但是这貌似不影响的..

    tasks[i] = new Task(d.DoTheJob);
    tasks[i].Start();
    
    
    

    就算是延迟..但是它的值还是不变的,不是么...比如,这里赋值为 tasks[1].Start();(这个延迟,还没有启动).然后下一个 tasks[2].Start()开始启动...但是他们的赋值...不会影响到对方的,在内存中只是等待状态而已...对吧...

    不是,我现在搜的是,为什么 类型要是 object. 而不能是它的派生类(也就是说为什么不能是它的类型).这个我不懂...想让你帮我解释一下...我想不通...

    2013年6月21日 5:30
  • 我想不通为什么不能是派生自 object类型的其他类型...
    2013年6月21日 5:32
  •  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.

    2013年6月21日 6:47
  • 不是这个原因——

    因为你一个类中嵌套自身的实例化,譬如这样照样死掉:

    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

    2013年6月22日 7:03
    版主
  • publicclassA     {         privateAa=newA();     }

    //和这个没有关系吧...大哥...

           
    2013年6月23日 0:00
  • 怎么没有关系?你试过我代码没有?照样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

    2013年6月23日 1:15
    版主
  • 我当然试过...我们现在的问题,不是你说的这个"递归调用构造函数本身"导致的无限循环....至于为什么overflow,我觉得就是多线程共同访问导致的....
    2013年6月25日 6:19
  • 你的问题是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

    2013年6月25日 6:57
    版主
  • 但是按照你说的,递归的构造(即死循环地构造对象).但是我没有在构造new哈...而且,貌似StackOverflow的情况貌似蛮多,我们想到是先是 死循环,但是这里不是在构造函数中递归哈...而且,StackOverflow不一定是那么直接的 循环,我觉得线程的访问也是有可能的...或者别的,但是你说的那个问题.这里根本就扯不到关系哈...
    2013年6月26日 11:14
  • 你首先尝试我的代码,报同样的错误。

    我承认,报同样的错误不一定证明说一定是死循环造成。可是为什么换成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

    2013年6月27日 1:20
    版主