c# - why does the thread get the demo.names is null? -
here code:
class program { static void main(string[] args) { (int = 0; < 200; i++) { console.writeline("---------" + i.tostring()); demo.testerror(); } } public class demo { public demo() { } public demo(int i) { index = i; } public static void testerror() { list<thread> threads = new list<thread>(); demo demo = null; (int = 0; < 1000; i++) { if (i % 10 == 0) { demo = new demo(i); } #region code1 thread t = new thread(() => { demo.setname(); var names = demo.names; string msg = null; if (names == null) { msg = demo.index.tostring() + " -" + thread.currentthread.managedthreadid.tostring() + "-is null"; console.write(msg); } else if (names == null || names.count <= 0) { msg = demo.index.tostring() + " -" + thread.currentthread.managedthreadid.tostring() + "-is zero"; console.write(msg); } else { msg = demo.index.tostring() + " -" + thread.currentthread.managedthreadid.tostring() + "-is ok" + "-" + string.join(",", names); } }); t.start(); #endregion threads.add(t); } (int = 0; < threads.count; i++) { threads[i].join(); } } public list<string> names; public int index; public object lockobj = new object(); public void setname() { if (names == null) { lock (lockobj) { if (names == null) { var tnames = new list<string>(); tnames.add("a"); system.threading.interlocked.compareexchange(ref names, tnames, null); } } } } }
run it, , shows(partial) :
---------60 750 -747-is null---------61 ---------62
...
---------95 960 -5174-is null---------96 ---------97
...
---------101 580 -3591-is null---------102 ---------103
...
---------112 720 -2193-is null---------113 ---------114
...
---------123 50 -2790-is null---------124 ---------125
...
---------133 420 -1237-is null---------134 ---------135
...
change code1 code2:
#region code2 thread t = new thread((obj) => { var d = obj demo; d.setname(); var names = d.names; ...//the same above }); t.start(demo); #endregion
it runs success! what's difference between
public thread(threadstart start);
and
public thread(parameterizedthreadstart start);
? , why demo.names
null or its'count zero?
they're different in parameterizedthreadstart
gets object input threadstart
doesn't, simple that.
so why 1 of them works , other doesn't? it's because of variable scope. once use parameterizedthreadstart
passes demo
variable parameter when for
loop iterates next run, doesn't change reference, whereas in first code you're using same object , sharing among threads.
the main problem being you've defined demo
variable outside for
block.so race condition occurring you're changing reference of variable (demo) briskly in loop, whereas it's still being used in threads.
demo demo = null; (int = 0; < 1000; i++) { if (i % 10 == 0) { demo = new demo(i); } ... }
if change code this, should fixed , work in both scenarios :
for (int = 0; < 1000; i++) { demo demo = null; if (i % 10 == 0) { demo = new demo(i); } ... }
Comments
Post a Comment