首页 新闻 赞助 找找看

求"从不同步的代码块中调用了对象同步方法"解决方法.

0
悬赏园豆:100 [已解决问题] 解决于 2009-03-25 12:13

我要实现一个Thread2每循环赛一次.都给Thread1一个脉冲.让其验证一次counter.符合的话会执行下去直到退出..不符合的话就返回Thread2..但我修改了多次在" Monitor.Pulse(this); "
都抛出一个" System.Threading.SynchronizationLockException: 从不同步的代码块中调用了对象同步方法。" 的异常..请问是什么问题引起的..有什么解决方法? 

C# code
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace TreadText { class Program { private int counter=0; static void Main(string[] args) { Program p = new Program(); p.DoText(); } public void DoText() { Thread[] myThreads = { new Thread(new ThreadStart(Decrementer)), new Thread(new ThreadStart(Incrementer)) //new Thread(new ThreadStart(Decrementer)), //new Thread(new ThreadStart(Incrementer)) }; int ctr=1; foreach (Thread myThread in myThreads) { myThread.IsBackground = true; myThread.Name = "Thread" + ctr.ToString(); ctr++; Console.WriteLine("[{0}] is started.",myThread.Name); myThread.Start(); Thread.Sleep(500); } foreach (Thread myThread in myThreads) myThread.Join(); } void Decrementer() { try { Monitor.Enter(this); while(counter<5) //if (counter < 10) { Console.WriteLine("[{0}] is waiting...counter is {1}", Thread.CurrentThread.Name, counter); Monitor.Wait(this); } while (counter > 0) { int temp = counter; temp--; Thread.Sleep(1); counter = temp; Console.WriteLine("[{0}] in Decrementer.counter :{1}", Thread.CurrentThread.Name, counter); } } finally { Console.WriteLine("[{0}] is Exiting", Thread.CurrentThread.Name); Monitor.Exit(this); } } void Incrementer() { try { Monitor.Enter(this); while (counter < 10) { int temp = counter; temp++; Thread.Sleep(1); counter = temp; Console.WriteLine("[{0}] in Incrementer.counter :{1}", Thread.CurrentThread.Name, counter); Monitor.Pulse(this); Monitor.Exit(this); } } finally { Console.WriteLine("[{0}] is Exiting", Thread.CurrentThread.Name); Monitor.Exit(this); } } } }

Keith的主页 Keith | 初学一级 | 园豆:100
提问于:2009-03-24 21:11
< >
分享
最佳答案
1

只有锁的当前所有者可以使用 Pulse 向等待对象发出信号。

你的问题出在下面这个循环,当第一次进入后当前线程交出了锁,但并没有再次申请锁,

第二次进入后当前线程已经不是这个锁的所有者,所以会出那个错误。

                while (counter < 10)
                {
                   
int temp = counter;
                    temp
++;
                    Thread.Sleep(
1);
                    counter
= temp;
                    Console.WriteLine(
"[{0}] in Incrementer.counter :{1}", Thread.CurrentThread.Name, counter);
                    Monitor.Pulse(
this);
                    Monitor.Exit(
this);
                }
下面是我修改的代码

       public void DoText()
        {
            Thread[] myThreads =
            {
                new Thread(new ThreadStart(Decrementer)),
                new Thread(new ThreadStart(Incrementer))
                //new Thread(new ThreadStart(Decrementer)),
                //new Thread(new ThreadStart(Incrementer))
            };
            int ctr=1;
            foreach (Thread myThread in myThreads)
            {
                myThread.IsBackground = true;
                myThread.Name = "Thread" + ctr.ToString();
                ctr++;
                Console.WriteLine("[{0}] is started.",myThread.Name);
                myThread.Start();
                Thread.Sleep(500);
            }
            foreach (Thread myThread in myThreads)
                myThread.Join();
        }

        void Decrementer()
        {
            try
            {
                Monitor.Enter(this);
                while(counter<5)
                //if (counter < 10)
                {
                    Console.WriteLine("[{0}] is waiting...counter is {1}", Thread.CurrentThread.Name, counter);
                    Monitor.Wait(this);
                }
                while (counter > 0)
                {
                    int temp = counter;
                    temp--;
                    Thread.Sleep(1);
                    counter = temp;
                    Console.WriteLine("[{0}] in Decrementer.counter :{1}", Thread.CurrentThread.Name, counter);
                }
            }
            finally
            {
                Console.WriteLine("[{0}] is Exiting", Thread.CurrentThread.Name);
                Monitor.Exit(this);
            }
        }

        void Incrementer()
        {
            try
            {
                while (counter < 10)
                {
                    Monitor.Enter(this);
                    int temp = counter;
                    temp++;
                    Thread.Sleep(1);
                    counter = temp;
                    Console.WriteLine("[{0}] in Incrementer.counter :{1}", Thread.CurrentThread.Name, counter);
                    Monitor.Pulse(this);
                    Monitor.Exit(this);
                    Thread.Sleep(0);
                }
               

            }
            finally
            {
                //Console.WriteLine("[{0}] is Exiting", Thread.CurrentThread.Name);
                //Monitor.Exit(this);
            }
        }


        private int _counter = 0;
        private object _lock = new object();

        private int counter
        {
            get
            {
                lock (_lock)
                {
                    return _counter;
                }
            }

            set
            {
                lock (_lock)
                {
                    _counter = value;
                }
            }
        }

 

eaglet | 专家六级 |园豆:17139 | 2009-03-25 07:59
其他回答(2)
0

学习学习!!!

子夜星辰 | 园豆:1613 (小虾三级) | 2009-03-25 08:48
0

在下面的代码中触发了同样的问题:

public async Task<T> GetAsync<T>(string key, Func<Task<T>> getCacheless, int cacheSeconds)
{
    if (client == null) return default(T);

    var result = await client.GetAsync<T>(key);

    if (result.Success)
    {
        return result.Value;
    }
    else
    {
        var value = await getCacheless();

        bool lockTaken = false;
        try
        {
            Monitor.TryEnter(key, 500, ref lockTaken);
            if (lockTaken)
            {
                if (!(await client.GetAsync<T>(key)).Success)
                {
                    client.Store(StoreMode.Add, key, value, new TimeSpan(0, 0, cacheSeconds));
                }
            }
        }
        finally
        {
            if (lockTaken) Monitor.Exit(key);
        }                

        return value;
    }
}
dudu | 园豆:31075 (高人七级) | 2016-02-03 14:53
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册