Haha, I skimmed the article at first, and at the end of the first page, I was ready to tear his head off (metaphorically) for teaching new threading programmers to use a static variable to test if a thread is complete.
Then I realized that not only did he show the proper way (events with WaitForSingleObject), but he noted on page one “Can you spot the error”?
An alright article, but I recommend “Advanced Windows” (the book) to really understand Win32 kernel objects and multithreading.
The “threaddone” variable (if it will remain using it) really should be of type volatile, or there exists some possibility of an optimization by the compiler of not checking it, if it determines it could be stored in a register, because it isn’t obvious that it’s being modified by another thread/process/device by the compiler.
A far more useful method that doesn’t involve compiler optimizations as a possible error is to use WaitForSingleObject and (if you want to use extern) the handle for the thread itself, and wait for it within the other thread, because this cannot be optimized into a bug. Yes, it is more CPU intensive, but it is also correct in all cases!
Sleep() under the Windows 32 API is not an inline function or a macro in this example. My point is that Sleep() is used as an example placeholder for some other code in a more useful thread, or at least it could be. In any case, the compiler doesn’t even care about Sleep, and may keep “threaddone” within a register. As a result, it is possible that a compiler may see the code in question as simply looking at the same value that doesn’t change, and therefore optimize the whole thing out of existence. In no way did I bring up the atomicity of accessing a boolean value: that’s a red herring, and no CPU that Windows runs natively (just in case someone somewhere is running Windows in an emulator on a processor I don’t know about) on has a problem with a boolean value access being atomic.
And I agree, adding multiple threads isn’t a solution to everything, and often gets complicated very quickly! The threading model for BeOS is both one of its greatest assets and liabilities simultaneously: easy to use (in theory) and difficult to get right in practice for common uses, especially for beginners in the world of threading. It is, however, much easier to write GUI apps under BeOS with the native multiple threads than it is to write Windows GUI apps with multiple threads, especially using MFC, which is the closest analog to using the BeOS Interface Kit. Where writing an application under Windows is much easier is that you aren’t forced to use more than one thread in the application, and can make it as simple as possible for multiple windows. I would personally advise those wishing to write GUI apps to first master writing GUI apps with everything in a single thread before they even think about writing a GUI app using multiple threads! As such, BeOS is a seductive trap for new programmers wishing to write GUI apps
I don’t if its me or what, but I have always had a knack for Java threads for some reason or another.
Thread t = new Thread();
t.start();
public void run(){
while(true){
System.out.println(“hi There”);
}
}
rather than:
CWinThread *p;
p = AfxBeginThread(¶m1, param2, …., paramx);
DWORD ThreadRoutine(LPVOID *params){
// dereference code
.
.
.
}
I prefer clean to messy and Java’s threading is clean until you start getting into synchronized blocks, etc. Unfortunately, with Java you can not take advantage of SMP.
Haha, I skimmed the article at first, and at the end of the first page, I was ready to tear his head off (metaphorically) for teaching new threading programmers to use a static variable to test if a thread is complete.
Then I realized that not only did he show the proper way (events with WaitForSingleObject), but he noted on page one “Can you spot the error”?
An alright article, but I recommend “Advanced Windows” (the book) to really understand Win32 kernel objects and multithreading.
The “threaddone” variable (if it will remain using it) really should be of type volatile, or there exists some possibility of an optimization by the compiler of not checking it, if it determines it could be stored in a register, because it isn’t obvious that it’s being modified by another thread/process/device by the compiler.
A far more useful method that doesn’t involve compiler optimizations as a possible error is to use WaitForSingleObject and (if you want to use extern) the handle for the thread itself, and wait for it within the other thread, because this cannot be optimized into a bug. Yes, it is more CPU intensive, but it is also correct in all cases!
Actually, the variable doesn’t have to be volatile is sleep() is a real function (but it may have to be is sleep() is an inline function or a macro).
BTW, I would very much like to know which CPU that Windows runs on isn’t able to guarantee the atomicity of a boolean access.
Overall, I’d recommend staying away from anyone saying that threads are easy. Threads offer few advantages over fibers but many disadvantages.
Sleep() under the Windows 32 API is not an inline function or a macro in this example. My point is that Sleep() is used as an example placeholder for some other code in a more useful thread, or at least it could be. In any case, the compiler doesn’t even care about Sleep, and may keep “threaddone” within a register. As a result, it is possible that a compiler may see the code in question as simply looking at the same value that doesn’t change, and therefore optimize the whole thing out of existence. In no way did I bring up the atomicity of accessing a boolean value: that’s a red herring, and no CPU that Windows runs natively (just in case someone somewhere is running Windows in an emulator on a processor I don’t know about) on has a problem with a boolean value access being atomic.
And I agree, adding multiple threads isn’t a solution to everything, and often gets complicated very quickly! The threading model for BeOS is both one of its greatest assets and liabilities simultaneously: easy to use (in theory) and difficult to get right in practice for common uses, especially for beginners in the world of threading. It is, however, much easier to write GUI apps under BeOS with the native multiple threads than it is to write Windows GUI apps with multiple threads, especially using MFC, which is the closest analog to using the BeOS Interface Kit. Where writing an application under Windows is much easier is that you aren’t forced to use more than one thread in the application, and can make it as simple as possible for multiple windows. I would personally advise those wishing to write GUI apps to first master writing GUI apps with everything in a single thread before they even think about writing a GUI app using multiple threads! As such, BeOS is a seductive trap for new programmers wishing to write GUI apps
I don’t if its me or what, but I have always had a knack for Java threads for some reason or another.
Thread t = new Thread();
t.start();
public void run(){
while(true){
System.out.println(“hi There”);
}
}
rather than:
CWinThread *p;
p = AfxBeginThread(¶m1, param2, …., paramx);
DWORD ThreadRoutine(LPVOID *params){
// dereference code
.
.
.
}
I prefer clean to messy and Java’s threading is clean until you start getting into synchronized blocks, etc. Unfortunately, with Java you can not take advantage of SMP.
>Unfortunately, with Java you can not take advantage of SMP
Bull…
The JavaVMs have for years mapped their threads to native threads, which runs parrallell on SMP systems.
Once the only threading model in the Sun VM were “green threads” which behaves like you said.
You are right, JVM’s have done this for years, but you can not control what processor a thread will run on. For example,
Thread t1, t2;
t1 = new Thread(“My Thread 1”);
t2 = new Thread(“My Thread 2”);
t1.start();
t2.start();
// now show me code where on a SMP enabled system
// I can pass thread t1 to processor 1 and thread t2
// to processor 2
// The answer is you can not UNLESS you JNI and this takes
// away from Java’s portability
.
.
.
}
public void run(){
while(true){
System.out.println(this.toString());
}
}
Hope this clarifies what I meant in my previous post.
>You are right, JVM’s have done this for years, but you can not control what processor a thread will run on. For example,
And you are right as well. Btw, can you do that nativly under linux ? Until recently (2.6 kernel) you couldn’t even do it with processes.