我要实现一个Thread2每循环赛一次.都给Thread1一个脉冲.让其验证一次counter.符合的话会执行下去直到退出..不符合的话就返回Thread2..但我修改了多次在" Monitor.Pulse(this); "
都抛出一个" System.Threading.SynchronizationLockException: 从不同步的代码块中调用了对象同步方法。" 的异常..请问是什么问题引起的..有什么解决方法?
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); } } } }
只有锁的当前所有者可以使用 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;
}
}
}
学习学习!!!
在下面的代码中触发了同样的问题:
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; } }