C# 值类型传参与引用类型传参 在多线程调用时的区别
看一道雅虎 的面试题
void test(int i) { lock(this) { if(i > 10) { i--; test(i); } } }
这道题问的是会不会产生死锁?想考的是这么递归的去锁,会不会死锁,但其实这个问题可以看出2个问题来。
- 这里多线程调用此方法时不会产生死锁,原因是
Lock语句对 “同一个线程多次锁同一个对象不予理会"
- 还有一个问题是 int i。 int是值类型,传参其实是值的一个副本。但是如果这里的参数换成引用类型,就会有同步的问题
void test(xxobject o) //这里o就是竞争资源,需要在其内部讲共用资源锁起来 { lock(this) { } }
比如:
public class StateObject { private int state = 5; public void ChangeState(int loop) { if (state == 5) { state++; Trace.Assert(state == 6, "race condition occurred after " + loop + " loops"); } state = 5; } } public class SampleTask { public void RaceCondition(object oj) { StateObject obj = (StateObject)oj; int i = 0; while (true) { Console.WriteLine(i); obj.ChangeState(i++); if (i > 200000) { break; } } } } //调用代码 StateObject obj = new StateObject(); for (int i = 0; i < 200; i++) { new Task(new SampleTask().RaceCondition, obj).Start(); }
以上代码会产生同步竞争。解决办法:
lock{ if (state == 5) { state++; Trace.Assert(state == 6, "race condition occurred after " + loop + " loops"); } state = 5; }