C++进行代码加速、多线程等知识点。

1、关于多线性进行全局变量的使用的时候为什么需要加锁?

a、在多线程中对全局变量进行处理的时候,如果涉及到在线程中对全局变量进行赋值的话,则需要进行加锁。

如果不加锁的话,容易导致全局变量在某个线程中被修改后,影响另一线程的数据处理。

b、全局变量不加锁主要是为了数据处理的正正确性,而不是为了防止导致多个线程同时操作同一个数据时出现程序崩溃。因为这种情况是不会产生的。

下面是一个多线程对多个全局变量进行赋值操作和读取操作。其都不会出现程序崩溃现象下面c、的代码也可以看出其不会导致崩溃。

c、下面是关于线程的join和detach的区别:

    int pthread_detach(pthread_t tid); 若成功则返回0,若出错则为非零。
    pthread_detach用于分离可结合线程tid。线程能够通过以pthread_self()为参数的pthread_detach调用来分离它们自己。
    如果一个可结合线程结束运行但没有被join,则它的状态类似于进程中的Zombie Process,即还有一部分资源没有被回收,所以创建线程者应该调用pthread_join来等待线程运行结束,并可得到线程的退出代码,回收其资源。
    由于调用pthread_join后,如果该线程没有运行结束,调用者会被阻塞,在有些情况下我们并不希望如此。例如,在Web服务器中当主线程为每个新来的连接请求创建一个子线程进行处理的时候,主线程并不希望因为调用pthread_join而阻塞(因为还要继续处理之后到来的连接请求),这时可以在子线程中加入代码
    pthread_detach(pthread_self())
或者父线程调用
    pthread_detach(thread_id)(非阻塞,可立即返回)
这将该子线程的状态设置为分离的(detached),如此一来,该线程运行结束后会自动释放所有资源。

  注意:第一:如果使用detach要小心点,就是如果线程的执行时间太久,会导致主线程会在上次子线程还没执行完就带着新数据或者在新一轮里改变了子线程里的一些全局变量。这是就需要记得加锁,来防止数据不一致。第二:如果detach后面的代码是需要子线程执行完后的处理结果的则不能使用detach方式,因为子线程还没有处理后结果,后面代码就进行结果读取的话,要么导致内存泄漏,要么是结果数据不对。

下面是使用pthread_join创建线程。

#include"3rdparty\include\pthread.h"
#include"opencv2\opencv.hpp"
using namespace cv;
int* hhnum; Mat img;
int threadnums = 6;
void* jia(void*params)
{	
	int args = *(int*)params;
	free(params);
	while (true)
	{	
	    img = imread("3.jpg");
		*hhnum =args;
		std::cout << *hhnum << std::endl;
		imwrite("4.jpg", img);
	}
}
void main()
{
	hhnum = new int[1];
	pthread_t *threads = (pthread_t*)calloc(threadnums, sizeof(pthread_t));
	for (size_t i = 0; i < threadnums; i++)
	{
		int*ptr = (int*)calloc(1, sizeof(int));
		*ptr = i;
		pthread_t thread;
		pthread_create(&thread, 0, jia, ptr);
		threads[i] = thread;
	}
	for (size_t j = 0; j < threadnums; j++)
	{
		try
		{
			pthread_join(threads[j], 0); //这个创建的线程是阻塞式的,只有当所有的线程结束后,程序才会往下执行。
		}
		catch (Exception e)
		{
			int i = 0;
		}
	}

}

  注意:这种这线程是不可分离线程,其需要等待所有的线程执行完成才可以继续执行。上面的代码会一直阻塞在主线程上。其一般跟joinable配合使用。其中joinable:代表该线程是否是可执行线程,其true代表可执行,false代表不可执行,不可执行意味着改线程要么没被创建,要么已经带有join是否相关资源了。其配合使用代码如下:

					if (t_cap.joinable()) {
						t_cap.join();
						++fps_cap_counter;
						cur_frame = cap_frame.clone();
					}

  注意:在调用碗join()后,其中joinable()就返回的就是false了、

下面使用pthread_detach来创建可分离线程。

#include"3rdparty\include\pthread.h"
#include"opencv2\opencv.hpp"
using namespace cv;
int* hhnum; Mat img;
int threadnums = 10;
void* jia(void*params)
{
	int args = *(int*)params;
	free(params);
	cvNamedWindow("krk");
	for (size_t i = 0; i < args; i++)
	{
		img = imread("3.jpg");
		*hhnum = args;
		//std::cout << *hhnum << std::endl;
		imwrite("4.jpg", img);
		cvWaitKey(100 - i);
		if (args == 3)
		{
			while (true)
			{			
			}
		}
	}
	return (void*)8;
}
void main()
{
	hhnum = new int[1];
	cvNamedWindow("kk");
	pthread_t *threads = (pthread_t*)calloc(threadnums, sizeof(pthread_t));
	for (size_t i = 0; i < threadnums; i++)
	{
		int*ptr = (int*)calloc(1, sizeof(int));
		*ptr = i;
		pthread_t thread;
		pthread_create(&thread, 0, jia, ptr);
		threads[i] = thread;
	}
	for (size_t j = 0; j < threadnums; j++)
	{
		try
		{
			pthread_detach(threads[j]);
			std::cout << j << std::endl;
		}
		catch (Exception e)
		{
			int i = 0;
		}
	}
	waitKey(0);
}

其输出结果是:


注意:其是立即返回的。并且但线程执行完后,系统会自动回收线程资源。其中第三个线程还一直在执行着。

   

猜你喜欢

转载自blog.csdn.net/yangdashi888/article/details/70346692
今日推荐