PrintHello()函数pthread示例是线程安全的吗?我在网上找到了这样的例子,但我不明白它们怎么会是线程安全的。另一方面,如果我在PrintHello()函数中的代码周围添加互斥锁,那么该示例将不是多线程的,因为所有线程都将排队等待前一个线程退出PrintHello()函数。此外,将其移动到类中也没有帮助,因为CreateThread()似乎不允许将该成员静态声明为指向非静态函数的指针。有什么办法解决这个问题吗?
#include <WinBase.h>
#include <stdio.h>
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
#define NUM_THREADS 500
DWORD PrintHello(LPVOID oHdlRequest)
{
long tid;
tid = (long)GetCurrentThreadId();
/* randomly sleep between 1 and 10 seconds */
int sleepTime = rand() % 10 + 1;
sleep(sleepTime);
printf("Hello World! It's me, thread #%ld!\n", tid);
return 0;
}
int main (int argc, char *argv[])
{
/* initialize random seed: */
srand (time(NULL));
HANDLE threads[NUM_THREADS];
long t;
DWORD nThreadID;
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
threads[t] = CreateThread(
// Default security
NULL,
// Default stack size
0,
// Function to execute
(LPTHREAD_START_ROUTINE)&PrintHello,
// Thread argument
NULL,
// Start the new thread immediately
0,
// Thread Id
&nThreadID
);
if (!threads[t]){
printf("ERROR; return code from CreateThread() is %d\n", GetLastError());
exit(-1);
}
}
}发布于 2013-05-13 16:17:23
由于您包含了WinBase.h,因此我假设您使用的是MSVC。MSVC CRT长期以来一直支持多线程访问-事实上,MSVC的当前版本不再支持非threadsafe的单线程CRT。我相信VS2003是支持单线程CRT的MSVC的最后一个版本。
在多线程CRT中,函数是线程安全的,如果它们在内部访问全局数据,它们将相互同步。因此,在ProcessRequest()中执行的每个printf()相对于其他线程中的其他printf()调用将是原子的(实际上,锁是基于流的,因此printf()调用将相对于使用stdout的其他CRT函数是原子的)。
例外情况是,如果您使用的I/O函数显式地记录为不获取锁(因此,出于性能原因,您可以自己对它们进行同步),或者如果您定义了_CRT_DISABLE_PERFCRIT_LOCKS,在这种情况下,CRT假定所有I/O都将在单个线程上执行。
请参阅http://msdn.microsoft.com/en-us/library/ms235505.aspx
POSIX做出了类似的保证,即printf()将是线程安全的:
引用(FILE *)对象的所有函数(名称以_unlocked结尾的函数除外)在内部使用flockfile()和funlockfile()来获得这些(FILE *)对象的所有权。
POSIX/UNIX要求printf()本身是原子的;从不同的线程对printf()的两个并行调用可以混合它们的数据是不合法的。但这两个写入可能会以任一顺序显示在输出上。
发布于 2013-05-13 16:14:17
代码通常不是线程安全的;printf通常不是可重入的。(一个实现可以将reentrace作为一个附加功能添加到其中,但我不知道有哪一个是这样做的。)你必须在它周围添加一些保护措施。(在Windows下,一个所谓的CriticalSection应该就足够了。)
你还必须找到一个线程安全的sleep的替代品;我找不到任何文档说它是可重入的(而Posix变体不是),但微软似乎没有一般的文档可重入。一种经典的解决方案是创建一个互斥锁,阻塞它,然后用所需的超时时间在它上面调用WaitForSingleObject;CreateWaitableTimer和WaitForSingleObject也应该可以工作。(正如我所说的,微软的文档非常有缺陷;但WaitForSingleObject必须是安全的,因为它被设计为在等待互斥时使用。)
还要注意,除非加入创建的线程,否则很可能会在main结束时运行,并且进程将在任何线程运行之前终止。(在Windows下,您可以使用WaitForSingleObject或WaitForMultipleObjects来加入。)
一个更好的解决方案是使用标准线程,如果你有一个支持它们的编译器,或者如果你不支持的话,可以使用Boost them。
https://stackoverflow.com/questions/16517067
复制相似问题