精华内容
下载资源
问答
  • python多线程两种调用方式
    千次阅读
    2021-03-18 11:34:20

    直接调用

    Thread类定义:

    class threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)

    Thread 的构造方法中,最重要的参数是 target,所以我们需要将一个 callable 对象赋值给它,线程才能正常运行。

    如果要让一个 Thread 对象启动,调用它的 start() 方法就好了。

    1 import threading

    2 import time

    3

    4 def sayhi(num): #定义每个线程要运行的函数

    6 print("running on number:%s" %num)

    8 time.sleep(3)

    9

    10 if __name__ == '__main__':

    12 t1 = threading.Thread(target=sayhi,args=(1,)) #生成一个线程实例

    13 t2 = threading.Thread(target=sayhi,args=(2,)) #生成另一个线程实例

    15 t1.start() #启动线程

    16 t2.start() #启动另一个线程

    18 print(t1.getName()) #获取线程名

    19 print(t2.getName())

    继承式调用

    自定义一个 Thread 的子类,然后复写它的 run() 方法。

    import threading

    import time

    class MyThread(threading.Thread):

    def __init__(self,num):

    threading.Thread.__init__(self)

    self.num = num

    def run(self):#定义每个线程要运行的函数

    print("running on number:%s" %self.num)

    time.sleep(3)

    if __name__ == '__main__':

    t1 = MyThread(1)

    t2 = MyThread(2)

    t1.start()

    t2.start()

    Thread 的生命周期

    1、 创建对象时,代表 Thread 内部被初始化。

    2、 调用 start() 方法后,thread 会开始运行。

    3、 thread 代码正常运行结束或者是遇到异常,线程会终止。

    更多相关内容
  • 调用MSVC CRT的函数_beginthread()或_beginthreadex()来创建线程。 _beginthread 参数和返回值 unsigned long _beginthread( void(_cdecl *start_address)(void *), //声明为void (*start_address)(void *)形式 ,...

    异步执行函数线程Dome

    调用MSVC CRT的函数_beginthread()或_beginthreadex()来创建线程。

    _beginthread 参数和返回值

    unsigned long _beginthread(
    void(_cdecl *start_address)(void *), //声明为void (*start_address)(void *)形式 ,一般指函数名称
    unsigned stack_size, //是线程堆栈大小,一般默认为0
    void *arglist //向线程传递的参数指针,一般为结构体
    );

    #include<stdio.h>
    #include<stdlib.h>
    #include<process.h>//线程头文件
    #include<Windows.h>
    
    
    void msg(void *p)
    {
    	char* str = (char*)p;
    	MessageBoxA(0, "窗口", str, 0);
    }
    
    void main()
    {
    
    	char ch1[20] = "第一条信息";
    	char ch2[20] = "第二条信息";
    	char ch3[20] = "第三条信息";
    
    	//开辟三个线程异步执行msg函数
    	_beginthread(msg, 0, &ch1);
    	_beginthread(msg, 0, &ch2);
    	_beginthread(msg, 0, &ch3);
    
    
    	system("pause");
    }

    执行效果:

    三个对话框同时弹出

    我们知道在Windows下创建一个线程的方法有两种,一种就是调用Windows API CreateThread()来创建线程;另外一种就是调用MSVC CRT的函数_beginthread()或_beginthreadex()来创建线程。相应的退出线程也有两个函数Windows API的ExitThread()和CRT的_endthread()。这两套函数都是用来创建和退出线程的,它们有什么区别呢?

    根据Windows API和MSVC CRT的关系,可以看出来_beginthread()是对CreateThread()的包装,它最终还是调用CreateThread()来创建线程。那么在_beginthread()调用CreateThread()之前做了什么呢?我们可以看一下_beginthread()的源代码,它位于CRT源代码中的thread.c。我们可以发现它在调用CreateThread()之前申请了一个叫_tiddata的结构,然后将这个结构用_initptd()函数初始化之后传递给_beginthread()自己的线程入口函数_threadstart。_threadstart首先把由_beginthread()传过来的_tiddata结构指针保存到线程的显式TLS数组,然后它调用用户的线程入口真正开始线程。在用户线程结束之后,_threadstart()函数调用_endthread()结束线程。并且_threadstart还用__try/__except将用户线程入口函数包起来,用于捕获所有未处理的信号,并且将这些信号交给CRT处理。

    所以除了信号之外,很明显CRT包装Windows API线程接口的最主要目的就是那个_tiddata。这个线程私有的结构里面保存的是什么呢?我们可以从mtdll.h中找到它的定义,它里面保存的是诸如线程ID、线程句柄、erron、strtok()的前一次调用位置、rand()函数的种子、异常处理等与CRT有关的而且是线程私有的信息。可见MSVC CRT并没有使用我们前面所说的__declspec(thread)这种方式来定义线程私有变量,从而防止库函数在多线程下失效,而是采用在堆上申请一个_tiddata结构,把线程私有变量放在结构内部,由显式TLS保存_tiddata的指针。

    那么_tiddata在什么时候会被释放呢?ExitThread()肯定不会,因为它根本不知道有_tiddata这样一个结构存在,那么很明显是_endthread()释放的,这也正是CRT的做法。不过我们很多时候会发现,即使使用CreateThread()和ExitThread() (不调用ExitThread()直接退出线程函数的效果相同),也不会发现任何内存泄露,这又是为什么呢?经过仔细检查之后,我们发现原来密码在CRT DLL的入口函数DllMain中。我们知道,当一个进程/线程开始或退出的时候,每个DLL的DllMain都会被调用一次,于是动态链接版的CRT就有机会在DllMain中释放线程的_tiddata。可是DllMain只有当CRT是动态链接版的时候才起作用,静态链接CRT是没有DllMain的!这就是造成使用CreateThread()会导致内存泄露的一种情况,在这种情况下,_tiddata在线程结束时无法释放,造成了泄露。

     
    #include <Windows.h>
    #include <process.h>
    void thread(void *a)
    {
        char* r = strtok( "aaa", "b" );
        ExitThread(0); // 这个函数是否调用都无所谓
    }
    int main(int argc, char* argv[])
    {
        while(1) {
            CreateThread(  0, 0, (LPTHREAD_START_ROUTINE)thread, 0, 0, 0 );
            Sleep( 5 );
        }
    return 0;
    }

    如果用动态链接的CRT (/MD,/MDd)就不会有问题,但是,如果使用静态链接CRT (/MT,/MTd),运行程序后在进程管理器中观察它就会发现内存用量不停地上升,但是如果我们把thread()函数中的ExitThread()改成_endthread()就不会有问题,因为_endthread()会将_tiddata()释放。

    这个问题可以总结为:当使用CRT时(基本上所有的程序都使用CRT),请尽量使用_beginthread()/_beginthreadex()/_endthread()/_endthreadex()这组函数来创建线程。在MFC中,还有一组类似的函数是AfxBeginThread()和AfxEndThread(),根据上面的原理类推,它是MFC层面的线程包装函数,它们会维护线程与MFC相关的结构,当我们使用MFC类库时,尽量使用它提供的线程包装函数以保证程序运行正确。

    原文地址:https://www.jb51.net/article/41459.htm

     

    线程的冻结和解冻调试:

    #include<stdio.h>
    #include<stdlib.h>
    #include<process.h>//线程头文件
    #include<Windows.h>
    
    
    
    
    
    void printNumber(void* vPtr)
    {
    	int *num = (int*)vPtr;
    	while (1)
    	{
    		printf("%d\n", (*num)++);
    		Sleep(1000);//休眠1秒
    	}
    }
    
    void main()
    {
    	int n1 = 10;
    	
    	_beginthread(printNumber, 0, &n1);
    	
    	//插入断点
    	system("pause");//阻塞主线程
    	//插入断点
    	system("pause");
    	//插入断点
    	system("pause");
    	//插入断点
    	system("pause");
    	//插入断点
    	system("pause");
    }

    打开线程调试窗口:

    system("pause") 函数阻塞线程执行

    多线程访问全局变量冲突问题:

    WaitForMultipleObjects是Windows中的一个功能非常强大的函数,几乎可以等待Windows中的所有的内核对象。等待多个线程或事件执行结束。

    函数原型为:

    DWORD WaitForMultipleObjects(

    DWORD nCount, // 线程个数

    CONST HANDLE *lpHandles, // 指向对象句柄数组的指针

    BOOL fWaitAll, // 释放等待所有

    DWORD dwMilliseconds // 超时间隔(毫秒)

    );

    参数解析:

    DWORD 就是 Double Word, 每个word为2个字节的长度,DWORD双字即为4个字节,每个字节是8位。

    nCount 指定列表中的句柄数量 最大值为MAXIMUM_WAIT_OBJECTS(64)

    *lpHandles 句柄数组的指针。lpHandles为指定对象句柄组合中的第一个元素 HANDLE类型可以为(Event,Mutex,Process,Thread,Semaphore)数组

    bWaitAll 等待的类型,如果为TRUE,表示除非对象都发出信号,否则就一直等待下去;如果FALSE,表示任何对象发出信号即可

    dwMilliseconds指定要等候的毫秒数。如设为零,表示立即返回。如指定常数INFINITE,则可根据实际情况无限等待下去

    函数的返回值有:

    WAIT_ABANDONED_0:所有对象都发出消息,而且其中有一个或多个属于互斥体(一旦拥有它们的进程中止,就会发出信号)

    WAIT_TIMEOUT:对象保持未发信号的状态,但规定的等待超时时间已经超过

    WAIT_OBJECT_0:所有对象都发出信号

    WAIT_IO_COMPLETION:(仅适用于WaitForMultipleObjectsEx)由于一个I/O完成操作已作好准备执行,所以造成了函数的返回

    返回WAIT_FAILED则表示函数执行失败,会设置GetLastError

    如bWaitAll为FALSE,那么返回结果相似,只是可能还会返回相对于WAIT_ABANDONED_0或WAIT_OBJECT_0的一个正偏移量,指出哪个对象是被抛弃还是发出信号。

    WAIT_OBJECT_0是微软定义的一个宏,你就把它看成一个数字就可以了。

    例如,WAIT_OBJECT_0 + 5的返回结果意味着列表中的第5个对象发出了信号

    如果程序中的nObjectWait是WAIT_OBJECT_0 + 5

    int nIndex = nObjectWait - WAIT_OBJECT_0;就是说nIndex =5也就表示第5个对象发出了信号

     

    DWORD WINAPI WaitForMultipleObjectsEx

      _In_ DWORD nCount,

      _In_ const HANDLE* lpHandles,

      _In_ BOOL bWaitAll,

      _In_ DWORD dwMilliseconds,

      _In_ BOOL bAlertable

    );  和上面差不多,详情参见:https://blog.csdn.net/liu4030127/article/details/9457275

    当 bWaitAll参数为FALSE可以等待其中之一的事件:示例如下

    HANDLE m_hEvent[2];    
      //两事件  
      
    m_hEvent[0]=CreateEvent(NULL, FALSE, FALSE, NULL);  
    m_hEvent[1]=CreateEvent(NULL, FALSE, FALSE, NULL);  
    CreateThread(NULL, 0, MyThreadProc, this, 0, NULL);  
    DWORD WINAPI MyThreadProc(LPVOID lpParam)  
    {   
    while(TRUE)  
     {  //每次等500毫秒   
     int nIndex = WaitForMultipleObjects(2, pThis->m_hEvent, FALSE,500);     
     if (nIndex == WAIT_OBJECT_0 + 1)   
     {  
     //第二个事件发生   //ExitThread(0);   //break;    
    }   
     else if (nIndex == WAIT_OBJECT_0) //第一个事件发生    
    {   
      //第一个事件  
       }    
    else if (nIndex == WAIT_TIMEOUT) //超时500毫秒    
    {   //超时可作定时用    
    }   
    }  
     OutputDebugString("线程结束. /n");  
     return 0L;}  
    #include<stdio.h>
    #include<stdlib.h>
    #include<process.h>//线程头文件
    #include<Windows.h>
    
    int num = 0;
    
    void run(void* vPtr)
    {
    	for (int i = 0; i < 100; i++)
    	{
    		num++;
    	}
    }
    
    void main()
    {
    	HANDLE hd[100]; //函数句柄   typedef void * ; 创建一个线程数组
    	for (int i = 0; i < 100; i++)
    	{
    		//_beginthread 返回值为 unsigned int 或 unsigned __int64
    		hd[i]=(HANDLE)_beginthread(run, 0,NULL);
    	}
    	
    	//等待线程全部结束
    	WaitForMultipleObjects(100, hd, TRUE, INFINITE);
    
    	printf("num=%d\n", num);
    
    	system("pause");
    }

    实际输出与理论值不一致,这就是多线程同时访问全局变量冲突造成的。

    Windows提供了许多内核对象来实现线程的同步。对于线程同步而言,这些内核对象有两个非常重要的状态:“已通知”状态,“未通知”状态(也有翻译为:受信状态,未受信状态)。Windows提供了几种内核对象可以处于已通知状态和未通知状态:进程、线程、作业、文件、控制台输入/输出/错误流、事件、等待定时器、信号量、互斥对象。

      你可以通知一个内核对象,使之处于“已通知状态”,然后让其他等待在该内核对象上的线程继续执行。你可以使用Windows提供的API函数,等待函数来等待某一个或某些内核对象变为已通知状态。

    你可以使用WaitForSingleObject函数来等待一个内核对象变为已通知状态:

    DWORD WaitForSingleObject(
    HANDLE hObject, //指明一个内核对象的句柄
    DWORD dwMilliseconds); //等待时间
      该函数需要传递一个内核对象句柄,该句柄标识一个内核对象,如果该内核对象处于未通知状态,则该函数导致线程进入阻塞状态如果该内核对象处于已通知状态,则该函数立即返回WAIT_OBJECT_0。第二个参数指明了需要等待的时间(毫秒),可以传递INFINITE指明要无限期等待下去,如果第二个参数为0,那么函数就测试同步对象的状态并立即返回。如果等待超时,该函数返回WAIT_TIMEOUT。如果该函数失败,返回WAIT_FAILED。

    函数返回值:

    WAIT_OBJECT_0表示函数成功执行且指定的对象被触发处于signaled有信号状态;
    WAIT_TIMEOUT表示函数成功执行但超时且对象没有被触发处于nonsignaled无信号状态;
    WAIT_FAILED表示函数执行失败,通常是由hHandle句柄不可用,可以调用GetLastError()查看。
    详细说明:该函数检测指定的对象的当前状态,若为nonsignaled则调用者线程将处于等待状态,在此状态下消耗少量的处理器时间直到对象状态改变为signaled或超时。值得注意的是超时时限范围为0~0x7FFF FFFF,上限是0x7FFF FFFF而不是无穷大0xFFFF FFFF。若设定值为0x8000 0000~0xFFFF FFFF将等同于0x7FFFF FFFF。若要使用大于上限值请使用无穷大。在函数返回之前,有一个等待函数会修改引起函数返回的对象的状态,比如将信号量减1。目前该函数可以等待的对象包括事件event、互斥体mutex、信号量semaphore、进程process和线程thread。

    把上面代码循环中添加

    for (int i = 0; i < 100; i++)
    	{
    		//_beginthread 返回值为 unsigned int 或 unsigned __int64
    		hd[i]=(HANDLE)_beginthread(run, 0,NULL);
    		//等待单个线程结束,才会执行下一步
    		WaitForSingleObject(hd[i], INFINITE);//同步
    	}

    使用 临界区解决多线程冲突:CRITICAL_SECTION

    临界区又称关键代码段,指的是一小段代码在代码执行前,他需要独占一些资源。程序中通常将多线程同时访问的某个资源作为临界区,需要定义一个CRITICAL_SECTION类型的变量,然后调用InitializeCriticalSection函数对变量进行初始化;

    函数声明:VOID InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection );

    lpCriticalSection:一个CRITICAL_SECTION结构指针,表示用于初始化的临界区;

    InitializeCriticalSection函数在内部设置了CRITICAL_SECTION结构的某些成员变量,所以他不会失败。

    为了将某一段代码定义为临界区,需要调用EnterCriticalSection函数;

    VOID WINAPI EnterCriticalSection(__inout LPCRITICAL_SECTION lpCriticalSection);

    该函数的作用是判断是否有线程访问临界区资源,如果没有,就改变CRITICAL_SECTION结构的成员变量的值,赋予当前线程访问权,函数立即返回;如果有线程正在访问资源,则进入等待状态,直到没有线程访问。

    释放资源函数:void WINAPI LeaveCriticalSection( _Inout_LPCRITICAL_SECTION lpCriticalSection);

    释放CRITICAL_SECTION结构指针:void WINAPI DeleteCriticalSection(_Inout_ LPCRITICAL_SECTION lpCriticalSection);

    #include<stdio.h>
    #include<stdlib.h>
    #include<process.h>//线程头文件
    #include<Windows.h>
    #include<time.h>
    
    #define N 10
    
    CRITICAL_SECTION cs; //声明临界区结构体
    int num = 0;
    
    void run(void* vPtr)
    {
    	for (int i = 0; i < N; i++)
    	{
    		EnterCriticalSection(&cs);//进入临界区
    		num++;
    		LeaveCriticalSection(&cs);
    	}
    }
    
    //声明操作系统可调用函数
    DWORD WINAPI myrun(void* vPtr)
    {
    	EnterCriticalSection(&cs);//进入临界区
    	for (int i = 0; i < 1000; i++)
    	{
    		num++;
    	}
    	LeaveCriticalSection(&cs);
    	return 0;
    }
    
    
    void main()
    {
    	InitializeCriticalSection(&cs);//初始化临界区
    
    	time_t strat, end;
    	time(&strat);//开始时间
    
    	HANDLE hd[N]; //函数句柄   typedef void * ; 创建一个线程数组
    	for (int i = 0; i < N; i++)
    	{
    		//_beginthread 返回值为 unsigned int 或 unsigned __int64
    		//hd[i]=(HANDLE)_beginthread(run, 0,NULL);
    		//等待单个线程结束,才会执行下一步
    		//WaitForSingleObject(hd[i], INFINITE);
    		hd[i]=CreateThread(NULL, 0, myrun, NULL, 0, NULL);//创建线程
    	}
    	
    	//等待线程全部结束
    	WaitForMultipleObjects(N, hd, TRUE, INFINITE);
    	//WaitForMultipleObjectsEx(N, hd, TRUE, INFINITE,TRUE);
    
    	time(&end);//结束时间
    	double dtime= difftime(end, strat);
    	printf("time=%f\n", dtime);
    
    	printf("num=%d\n", num);
    
    	DeleteCriticalSection(&cs);//释放CRITICAL_SECTION结构指针
    	system("pause");
    }

     

     

     

    展开全文
  • linux多线程调用同一个函数解析

    千次阅读 2017-11-03 13:53:58
    问题背景:在工作中遇到过一个问题,就是在两个线程同时调用同一个函数的时候,到底是应该在这个函数的内部什么处理上加上互斥。...2.同一个进程中的两个线程调用同一个处理函数 3.两个不同进程中

    原文地址:http://blog.csdn.net/mq_ydn3102/article/details/8546722

    问题背景:在工作中遇到过一个问题,就是在两个线程同时调用同一个函数的时候,到底是应该在这个函数的内部什么处理上加上互斥。原因又是什么?

    为了调查这个问题,我决定从以下三方面调查

    1.线程中函数的调用

    2.同一个进程中的两个线程调用同一个处理函数

    3.两个不同进程中的两个线程调用同一个处理函数


    1.线程中函数的调用

    每个进程都会有自己的虚拟地址空间,同一个进程中的每个线程都会在这个虚拟空间中,并被分配相应的资源。
    线程中的函数实体是在内存中,而函数中的局部变量则会一次被push到栈中。
    如果是A函数调用B函数,则会先将A函数的参数和局部变量push到队列中,再将B函数的参数和局部变量push到队列中
    具体如下(参数是以从右到左压入栈中, __stdcall与__cdecl调用约定都是这么处理的):

    void fun(param1, param2,. param3....paramN)
    {
    value1;
    value2;
    ...
    valueN;
    }

    如果执行上面的函数在栈中会这样变化

    1:将fun函数的入力参数从右到左依次压入到栈中。

    2:将fun函数的指针压入栈中

    3:将ebp,ebx等寄存器入栈保存
    4:在栈中依次为各个变量分配空间

    执行后的处理:

    1.释放变量空间

    2.弹出个寄存器

    3.ret,弹出eip,返回主调方代码

    4.释放参数空间

    2.两个线程调用同一个函数

    两个线程中的函数的局部变量由于是保存在不同的线程中,因此不需要进行互斥处理

    3.两个不同进程中的两个线程调用同一个处理函数

    同样,两个线程中的函数的局部变量由于是保存在不同的线程中,因此不需要进行互斥处理

    结论:
    因此需要互斥处理的,一般是函数中有全局变量,有动态申请的空间,有静态局部变量,有需要进程数据循环发送之类的操作需要进行互斥处理

    展开全文
  • C/C++中,函数的本质是一段可执行代码,代码包括了局部变量、全局变量的地址等等。到汇编语言的级别,变量函数等都可以视为汇编的代码片段。函数的本质就是一个可执行...当一个线程执行一个函数的时候,复制函数...

    C/C++中,函数的本质是一段可执行代码,代码包括了局部变量、全局变量的地址等等。到汇编语言的级别,变量函数等都可以视为汇编的代码片段。函数的本质就是一个可执行代码片段的集合

    线程的详细介绍:http://www.cnblogs.com/tracylee/archive/2012/10/29/2744228.html
    一个线程有自己的空间,有自己的局部变量。当一个线程执行一个函数的时候,会复制函数的代码段到自己的线程空间,之后执行该代码段。对于局部变量,每个线程会保存一个局部变量的副本,因为局部变量是保存在栈内存,所以一个线程更改局部变量不会影响其他线程的局部变量。全局变量是保存在堆内存上的,因此可以理解为线程是直接操作堆内存上的全局变量,因此如果一个线程改了全局变量,那么其他线程对应的全局变量肯定会更改,因为堆内存只有一个。

    在多线程编程的过程中,所谓的添加互斥量、锁和条件变量等,本质上是为了保护堆内存上的东西,或者说是全局变量。所谓的竞争条件也是指的全局的,函数内部的局部的东西,不会引起竞争!!!!!

    可以这么认为,对于C++11中的std:thread来说,函数是其执行的基本单位,这里说的函数包括普通函数、函数对象、std::funtion、仿函数、lambda表达式等。执行的时候,线程会复制函数的代码片段到自己的线程空间中去执行。线程空间的本身是封闭的,也就是说一个同级别的线程不能更改另一个线程的代码片段。。我们说的线程之间的通信,本质上说的是通过全局变量的状态,使得不同线程之间可以相互通信!!!

    对于类的成员函数来说,线程复制函数的时候,类的成员变量相对于线程来说也是全局!!!!

    #include <iostream>
    #include <thread>
    #include <mutex>
    #include <condition_variable>
    #include <chrono>
    
    static int N = 0;
    
    void fun(int n) {
      int t = 0;
      for (int i = 0; i < n; ++i) {
        ++t;
        ++N;
      }
      std::this_thread::sleep_for(std::chrono::milliseconds(100));
      std::cout << "local: " << t << std::endl;
      std::cout << "global: " << N << std::endl;
    }
    
    class C {
    public:
      void fun(int n) {
        int t = 0;
        for (int i = 0; i < n; ++i) {
          ++t;
          ++_N;
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        std::cout << "local: " << t << std::endl;
        std::cout << "global: " << _N << std::endl;
      }
    
      int _N;  // 这里的_N相对于fun函数是全局的!!!!!!!
    };
    
    int main() {
      // 函数的例子
      std::cout << "function example:\n";
      std::thread t1(fun, 100000);
      std::thread t2(fun, 100000);
      t1.join();
      t2.join();
      
      std::this_thread::sleep_for(std::chrono::milliseconds(500));
    
      // 类的例子
      std::cout << "\nclass example:\n";
      C c;
      c._N = 0;
      std::thread t3(&C::fun, &c, 100000);
      std::thread t4(&C::fun, &c, 100000);
      t3.join();
      t4.join();
    
      return 0;
    }
    

    一种可能的执行结果:

    function example:
    local: 100000
    global: 109248
    local: 100000
    global: 109248
    
    class example:
    local: 100000
    global: 115581
    local: 100000
    global: 115581
    
    展开全文
  • 多线程访问同一函数

    千次阅读 2017-08-07 21:58:06
    线程访问同一函数时,一般情况下是互不影响的,但是当函数中存在全局变量或是static静态变量时,各个线程会得到不确定的结果
  • 一个函数能否两个线程同时调用

    千次阅读 2018-09-21 09:21:23
    一个函数能否两个线程同时调用 其实你可以这样想,函数本身只是代码,代码是只读的,无论多少个线程同时调都无所谓(因为只读嘛)。但是函数里面总要用到数据,如果数据属于线程(比如函数参数、局部变量,...
  • 多线程调用static方法线程安全问题

    千次阅读 2021-11-10 15:44:42
    最近在工作中遇到了线程安全的问题,是在一个方法中调用了静态方法解析Date的字符串。 因为 SimpleDateFormat这个类是线程不安全的,所以不能在静态方法中定义全局的成员变量。 @Test void contextLoads() { ...
  • 最近在研究多线程,然后突然想到如果两个线程同时访问一个函数的话,要不要加锁呢,加锁怎么加,不加又怎样这样的问题..然后去网上找了些帖子学习学习...... 上面的代码明显执行串了!!!! 函数本身只是代码,代码是...
  • 一个函数能否两个线程同时调用 其实你可以这样想,函数本身只是代码,代码是只读的,无论多少个线程同时调都无所谓(因为只读嘛)。但是函数里面总要用到数据,如果数据属于线程(比如函数参数、局部变量,存在栈...
  • ``` void ClassA::Fun1() { std::thread t(&ClassA::Fun2); // 测试过这种std::thread t(std::mem_fn(ClassA::Fun2),this); // 也不行 t.join(); } void ClassA::Fun2() { // do sth... ...
  • 多线程调用静态方法

    千次阅读 2015-10-19 16:20:55
    一、文章来由项目需求,可能要在多线程中使用静态方法。二、静态方法与线程安全类的成员分为两类,静态成员(static member)和实例成员(instance member)。静态成员属于类,实例成员则属于对象,即类的实例。 我们...
  • 多线程调用函数理解

    千次阅读 2012-12-13 11:16:29
    1.多线程调用同一个函数的理解 多线程调用一个函数和一个线程调用一个函数是一样的,关键要看你的函数是否使用了一些全局的东西。 函数的调用有自己的栈,每个函数的栈都是独立的. 唯一要考虑的是,在调用这个...
  • QT多线程中槽函数如何执行分析

    千次阅读 多人点赞 2020-04-09 23:54:28
    则等同于直接连接 如果发射信号的线程和接受者所依附的线程不同,则等同于队列连接 也就是这说,只存在下面两种情况 直接连接(Direct Connection) 当信号发射时,槽函数将直接被调用。 无论槽函数所属对象在哪个线程...
  • 调用pthread_create 第三个和第四个参数不为空时,要注意第四个参数的传递方法 一段流行的代码: #include #include using namespace std; #define NUM_THREADS 10 void* say_hello(void* args) { int i = ...
  • 易语言调用API之进程和线程函数

    千次阅读 2020-06-15 09:23:25
    进程和线程是我们制作游戏外挂的重点,设计多线程,进程的控制。 API之进程和线程函数 CancelWaitableTimer 这个函数用于取消一个可以等待下去的计时器操作 CallNamedPipe 这个函数由一个希望通过管道通信的一个...
  • 首先是多线程模块的多种制作方法和调用方法,其次每种多线程模块都实现免注册到系统调用,和免杀软的查杀,更重要的是示范了多种多线程模块的调用方法。 以下是所有视频的链接: 全部教程播单:...
  • 多线程时, 几个线程间输出信息是交叉在一起的, 但你又没有区分是哪个线程输出的, 所以你自己就误认为是同一个线程输出的东西改变了. 实际上是你自己的理解错误. 所有线程都用cout输出内容,你如何判断哪些内容...
  • 再一看跨线程信号槽调用,所以猜测跟多线程有关。排查过程中各种换信号、改参数都没有效果,偶然间把接收对象的创建移至主线程,槽函数居然执行成功了。本着有问题看手册的原则,在手册中找到了如下的说明: 大体...
  • VC++多线程函数调用

    千次阅读 2013-05-29 13:59:29
    在VC++中创建线程函数可以用API 或者MFC封装的多线程函数。。   函数原型 MSDN中CreateThread原型: HANDLE CreateThread(  LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD  SIZE_T dwStackSize, ...
  • c++中线程使用同一个函数

    千次阅读 2018-08-14 10:18:33
    在创建线程池(构造函数中)时创建若干个线程,起始时由于任务队列中没有任务,创建的每一个线程都处于阻塞状态。使用pthread_create函数创建线程时把所有的线程与同一个函数关联在一起,也就是产生如下的代码: ...
  • 我参考了很资料,都很零碎。最后我不得已把run1(),run2(),run()全部声明为static,还是报错:"Severity Code Description Project File Line Error (active) argument of type "void (*)(A &a)" is incompatible ...
  • 当run()函数结束之后,这个线程会被终结,但创建的QThread对象仍然存在,且创建的子线程可以循环使用。 2.start()函数调用:QThread只是new出来的一个对象,当调用start()之后,它会新建一个线程,并把...
  • link中用select调用一个函数,是不是多线程调用的?听说多线程可以节省时间?
  • 多线程调用类的成员函数的实现

    千次阅读 2012-02-21 20:44:35
    该方法实现了多线程灵活的调用类的成员函数。代码如下: #include #include #include //g++ -lpthread -o cpro cpro.cpp class triangle { private: int length; int width; int height; public: ...
  • C语言多线程编程-线程的基本函数

    万次阅读 多人点赞 2017-04-06 22:33:21
    线程操作函数线程属性控制函数
  • 要求入口函数必须是类的静态函数。 通常,可以采用thunk,或者模板来实现。 因C++ 11中引入了 std::async ,可以很好的解决这个问题了。 值得注意的是,在循环中 std::async 创建线程,我试了好多次总是失败,...
  • 多线程调用同一静态方法有多线程问题吗项目中有类的public static方法有可能多线程同时调用,所以有这个疑问,大致网上查了下自己没有试验过。 只要在静态函数中没有处理多线程共享数据,就不存在着多线程访问同...
  • 最近在研究多线程,然后突然想到如果两个线程同时访问一个函数的话,要不要加锁呢,加锁怎么加,不加又怎样这样的问题…然后去网上找了些帖子学习学习… 上面的代码明显执行串了!!! 函数本身只是代码,代码是只读的,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 785,227
精华内容 314,090
关键字:

下面的函数会被多线程调用