主线程退出,子线程会退出吗?子线程崩溃,主线程会退出吗?

        记得以前刚接触多线程编程时,作为一个新手遇到的一个问题就是:我创建的子线程为什么没有跑起来?如以下最简单的一个程序:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>

void *thread_function(void *arg);
char message[] = "THREAD_TEST";
struct test
{
	int a;
	int b;
	int c;
};
struct test outpara;

int main()
{
	int res;
	pthread_t a_thread;
	void *thread_result;
	struct test para = {
		.a = 10,
		.b = 20,
		.c = 30,
	};
	res = pthread_create(&a_thread, NULL, thread_function, (void *)&para);
	if(res != 0)
	{
		perror("Pthread_create");
		exit(EXIT_FAILURE);
	}

	printf("the thread has finish, return %d\n", ((struct test*)thread_result)->a);

	exit(EXIT_SUCCESS);
}

void *thread_function(void *arg)
{
	struct test inpara = *(struct test*)arg;
	printf("thread is running, the parameter is %d, %d, %d\n", inpara.a,inpara.b, inpara.c);
	sleep(300);
	outpara.a = 100, 
	outpara.b = 200,
	outpara.c = 300,
	pthread_exit(&outpara);
}

执行结果却是诡异的:

 

        大部分情况子线程就没有执行起来,偶尔会有一次子线程执行了。这是为什么呢?这是因为进程退出时,其创建的子线程都会被终止。那有没有办法让主线程退出时,子线程继续执行呢?有一个函数可以实现:pthread_exit()。

         我们 man pthread_exit 可以看到:

 pthread_exit 函数会终止调用线程,但在线程终止时,进程共享资源不会被释放,只有进程中的最后一个线程终止时,进程共享资源才会释放。

#include "Thread.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/syscall.h>
#include <signal.h>

namespace CurrentThread
{
    __thread int tCachedTid = 0;
 
    void cacheTid()
    {
        if(tCachedTid == 0)
        {
            printf("first time get tid\n");
            tCachedTid = (int)syscall(SYS_gettid);
        }
    }
 
    inline int tid()
    {
        if(tCachedTid == 0)
        {
            cacheTid();
        }
 
        return tCachedTid;
    }
}

class CMyThread: public CThread 
{
public:
    CMyThread();
    ~CMyThread();

    virtual void threadProc();
};

CMyThread::CMyThread(): CThread("myThread")
{

}

CMyThread::~CMyThread()
{

}

void CMyThread::threadProc()
{
    int count = 5;
    while(count--)
    {
        sleep(1);
        printf("in CMyThread, threadID = %d\n", CurrentThread::tid());
    }

    pthread_exit(NULL);
}


int main()
{
    CMyThread *myThread = new CMyThread();
    myThread->createThread();

    printf("exit main thread!\n");

    pthread_exit(NULL);
    return 0;
}

执行结果:

        若是主线程调用 pthread_exit() 进行退出,则其创建的子线程会继续执行,直到整个进程终止。假如主线程用 return 或 exit() 进行退出,则整个进程就退出了,子线程可能还没来得及执行。

        那如果子线程崩溃了,整个进程会结束吗? 如我在子线程里对NULL指针进行操作,这样会产生一个 SIGSEGV 信号:

#include "Thread.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/syscall.h>
#include <signal.h>

namespace CurrentThread
{
    __thread int tCachedTid = 0;
 
    void cacheTid()
    {
        if(tCachedTid == 0)
        {
            printf("first time get tid\n");
            tCachedTid = (int)syscall(SYS_gettid);
        }
    }
 
    inline int tid()
    {
        if(tCachedTid == 0)
        {
            cacheTid();
        }
 
        return tCachedTid;
    }
}

class CMyThread: public CThread 
{
public:
    CMyThread();
    ~CMyThread();

    virtual void threadProc();
};

CMyThread::CMyThread(): CThread("myThread")
{

}

CMyThread::~CMyThread()
{

}

void CMyThread::threadProc()
{
    int count = 5;
    while(count--)
    {
        sleep(1);
        printf("in CMyThread, threadID = %d\n", CurrentThread::tid());
    }
    char *p = NULL;
    memcpy(p, "test", 4);

    pthread_exit(NULL);
}


int main()
{
    CMyThread *myThread = new CMyThread();
    myThread->createThread();

    sleep(10);
    printf("exit main thread!\n");
    
    return 0;
}

可以看到进程结束了,没跑用例前我以为子线程崩溃主线程不会有影响,但是错误的。因为这里涉及到了信号的处理行为,子线程产生的信号应该也算是此进程产生的信号,那信号对应的处理方式是什么呢?这里找到 kernel 相关头文件里有说明 signal.h 

 

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Python 使用的是基于线程的并发模型,但是默认的全局解释器锁(Global Interpreter Lock, GIL)限制了在同一时刻只有一个线程在执行Python字节码。这就意味着在Python的单进程中,多线程只能用于I/O密集型任务,因为这时线程间的切换并不涉及到CPU计算资源的竞争。 因此,在Python中,线程本身并不直接阻塞线程。然而,如果线程执行了I/O操作或其他阻塞式的操作(如文件读写、网络请求等),则整个进程被阻塞,因为GIL不允许其他线程进入执行状态。此时,线程实际上也被阻塞了,直到线程完成其操作并返回执行结果。 举个例: ```python import threading import time def long_running_task(): print("Starting a blocking I/O task...") # 模拟I/O操作,这里只是简单地让线程睡眠几秒 time.sleep(5) print("I/O task finished.") # 创建一个线程实例,并通过目标函数和参数初始化 t = threading.Thread(target=long_running_task) # 开始线程 t.start() print("Main thread is still running.") ``` 在这个例中,尽管`main_thread`继续执行并打印了消息,但由于`long_running_task`中包含了一个模拟的长时间I/O操作,所以整个程序实际上被阻塞到了`time.sleep(5)`这一行,直到I/O操作完成。 解决阻塞问题的一种常见做法是将I/O密集型任务放在单独的进程中运行,而不是在同一个线程中。这样,即便这个进程内的某个线程被阻塞,也不影响到其他线程或进程内的其他操作。对于CPU密集型任务来说,多线程可以在Python中有效地利用多核处理器,因此在这种情况下,GIL通常不成为性能瓶颈。 --- --- 相关问题 --- 1. 如何在Python中安全地处理GIL以提高多线程程序的性能? 2. 是否有纯Python实现的替代方案,可以在多核处理器上充分利用硬件资源? 3. 在哪些场景下,多线程在Python中的使用效率比单一进程更高?
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值