cuándo exactamente se 'rompe' un hilo

First of all, I'm new to MT, so I apologise for any stupid/obvious things I might say :)

Let's say you have these thread callback functions for windows:

unsigned int __stdcall ThrdFuncA(void* param)
{
    std::wstring s(L"Hello World\n");
    std::wcout << s;
    return 0;
}

unsigned int __stdcall ThrdFuncB(void* param)
{
    std::wcout << L"Hello " << L"World" << std::endl;
    return 0;
}

What I noticed is, when I ran ThrdFuncA with 4 threads at the same time, and re-running it 100 times, the output would always be

Hello World
Hello World
Hello World

etc.

but when I ran ThrdFuncB with 4 threads at the same time, and re-running it 100 times, the output would sometimes be

Hello WorldHello World

Hello World
Hello World
Hello WorldHello World

Hello World

But this raises questions, especially since the first version always works. Does this mean that a thread never "breaks" when executing an external function, but always finishes that function? Is this OS specific? When exactly will a thread "break"?

preguntado el 10 de marzo de 12 a las 16:03

@Griwes I have, I didn't find any explanation regarding this matter in the articles I read. Feel free to downvote silently or help me on my way. -

It did not, but thank you for pointing me in the right direction -

since the first version always works No, you made an invalid conclusion. You don't have even hace casi enough evidence to suggest "always"; in fact, you just got "lucky" because of the timing of the execution of that particular code. -

Unsynchronised concurrent execution contexts aren't sequenced at all with respect to one another (hence "concurrent"). Everything you see is more or less a coincidence. -

Note: In C++11 (but not C++03) the standard guarantees there will be no internal data races (thus just means you can not break the stream). But it no guarantee that your characters will not be interleaved so your assumption that ThrdFuncA always works is not correct. It is the responsibility of the application to provide mutual exclusive accesses to the resource (ie. The old C++ adage we do not want everybody to pay for an expensive operation (locking) that only a few people need so you must do it yourself). -

3 Respuestas

Preemptive threads - the sort that your C++ example has - break at whatever point they feel like. So, it could be anything from coincidence up that shows the output you expect - more or less at random.

That is the nature of preemptive threads: you might be able to hint (with yield or some equivalent) that this is a good time to jump to another thread, and some operations might block and trigger another thread to run, but you can't ever determine when your thread might be switched away from.

In the much less common or popular cooperative threading systems, all switching is done at predictable times. This is vaguely convenient, but it is easy for things to accidentally block thread switching when it would be nice, so they are not very much in favour.

respondido 10 mar '12, 16:03

Just to be clear on what you mean by "break." On a truly parallel system with 4 processors (one for each of your threads) then the threads will never stop executing. Each thread is actively printing to a shared resource (in this case the output buffer) and it is very likely that the threads will write to the output buffer simultaneously, thus giving you interleaved output.

On a single core system, at any given moment, the operating system will stop one thread and run another thread. Since this can happen at any moment, the string data sent to the output buffer (the screen) can be in strange inter leavings.

Echa un vistazo a exclusión mutua. For a shared resource (std::cout), you can guard critical sections of code by requiring threads obtain a lock so that only one thread can access the resource at once. Locks are necessary for correctness in preemptive multithreaded system. See condiciones de carrera

respondido 10 mar '12, 16:03

What if you have more threads running than you have cores? Then they would still break, right? - xcrypt

Yes, for simplification purposes I didn't mention that. In reality, even with four cores and four threads, the operating system and other background processes still need to run. The point is that your code should expect that any execution interleaving is possible. - Chris

There is probably a mutex lock on cout calls, so serializing them. If you 'count' one complete "Hello World\n" string then the cout method core code will not be interrupted and reentered from another thread because of the lock. This results in unbroken output of the string.

If you make multiple calls with substrings and a newline, it's quite possible that another thread will get the lock in between the calls, so 'mixing up' the substrings and newline.

respondido 10 mar '12, 17:03

El estándar lo hace no guarantee this. - martín york

Maybe not, but the OP's output strongly suggests it! - Martín James

No it does not. That is probably the worst assumption you can ever make (and will get people killed). It merely looks like he is getting lucky. - martín york

Look again! 'Hello', 'World' and 'CRLF' are not split anywhere in the OP's o/p. Mixed up, just as if different threads are getting inside a lock, but not split and no characters are missing/corrupted. What are the chances of that happening by chabnce, with no lock? Note that I am not suggesting that this behaviour should be relied upon, just explaining the symptoms. - Martín James

What are the chances. Quite high I would think. - martín york

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.