thread 线程使用和解析

多线程是游戏开发必备知识。无论是操作系统的互斥锁还是网络通信的资源管理,多线程并发是永远要熟练其使用的知识。

例子1:

#include "stdafx.h"
#include<atomic>
#include <thread>
#include <iostream>

std::atomic<int> a(10);

std::atomic_llong total = {0};//定义为原子操作,保证多线程互斥访问

void funCount(int)
{
	for (long long i = 0; i <100000000LL; i++)
	{
		total+=i;
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	std::thread t1(funCount,0);//线程创建后由操作系统启动和运行,具有不可控性
	std::thread t2(funCount,0);
	t1.join();//join的运行依赖于主线程,当主线程退出时会强制关闭依附于它的子线程,并执行资源回收。调用即主线程被挂起等待join入的子线程运行完再执行新的线程,也就是说线程t2属性的更改,在于t1执行完成之后
	t2.join();//detach的区别在独立于主线程,与主线程同级,就面临一个问题:当主线程退出时,要保证detach的线程不在访问主线程的资源,否则会报错。
	//t2.detach();

	;

	std::cout<<__FUNCTION__<<":"<<total<<"\t"<<a.is_lock_free()<<std::endl;
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>//确认线程结束,输入的是120,线程不在对total进行读取
	total.store(120);

	std::cout<<__FUNCTION__<<":"<<total<<"\t"<<a.is_lock_free()<<std::endl;

	return 0;
}

为了验证t2的更改在属性线程t1执行完成之后,有如下例子:

int _tmain(int argc, _TCHAR* argv[])
{
	std::thread t1(funCount,0);
	std::cout<<__FUNCTION__<<":"<<total<<"\t"<<a.is_lock_free()<<std::endl;
	std::thread t2(funCount,0);
	std::cout<<__FUNCTION__<<":"<<total<<"\t"<<a.is_lock_free()<<std::endl;
	t1.join();

	//t2.detach();

	;

	std::cout<<__FUNCTION__<<":"<<total<<"\t"<<a.is_lock_free()<<std::endl;
	t2.detach();
	//total.store(120);//访问当前值试试,形成互斥
	std::cout<<__FUNCTION__<<":"<<total<<"\t"<<a.is_lock_free()<<std::endl;

	std::cout<<__FUNCTION__<<":"<<total<<"\t"<<a.is_lock_free()<<std::endl;

	return 0;
}

因为t2还处于默认状态。

什么是默认状态:

在任何一个时间点上,线程是可结合的(joinable),或者是分离的(detached)。一个可结合的线程能够被其他线程收回其资源和杀死;在被其他线程回收之前,它的存储器资源(如栈)是不释放的。相反,一个分离的线程是不能被其他线程回收或杀死的,它的存储器资源在它终止时由系统自动释放。

线程的分离状态决定一个线程以什么样的方式来终止自己。在默认情况下线程是非分离状态的,这种情况下,原有的线程等待创建的线程结束。只有当pthread_join()函数返回时,创建的线程才算终止,才能释放自己占用的系统资源。而分离线程不是这样子的,它没有被其他的线程所等待,自己运行结束了,线程也就终止了,马上释放系统资源。程序员应该根据自己的需要,选择适当的分离状态。所以如果我们在创建线程时就知道不需要了解线程的终止状态,则可以pthread_attr_t结构中的detachstate线程属性,让线程以分离状态启动。

基于此,如果线程t2实现了睡眠的话,就会明显出现下面的结果(如果主线程结束的比t2早,而t2仍未结束计算,则可能出现中断。如下的代码结束后没有出现中断,暂时模拟不出中断待续)

难道和使用了原子类型有关,不对,只有一个可能就是t1回调和main执行的过程中,它已经结束了。

int _tmain(int argc, _TCHAR* argv[])
{
	std::thread t1(funCount,0);

	std::cout<<__FUNCTION__<<":"<<total<<"\t"<<total.is_lock_free()<<std::endl;

	std::cout<<__FUNCTION__<<":"<<total<<"\t"<<total.is_lock_free()<<std::endl;

	t1.detach();

	//

	;

	std::cout<<__FUNCTION__<<":"<<total<<"\t"<<total.is_lock_free()<<std::endl;

	//total.store(120);//访问当前值试试,形成互斥
	std::cout<<__FUNCTION__<<":"<<total<<"\t"<<total.is_lock_free()<<std::endl;

	std::cout<<__FUNCTION__<<":"<<total<<"\t"<<total.is_lock_free()<<std::endl;
std::thread t2(funCount,0);t2.detach();
	return 0;
}

这样子创建也没有出现中断。。机子性能太好了?绝对不是,应该是某个概念我没理解对。

时间: 2024-11-05 07:57:14

thread 线程使用和解析的相关文章

Hystrix线程隔离技术解析-线程池(转)

认识Hystrix Hystrix是Netflix开源的一款容错框架,包含常用的容错方法:线程隔离.信号量隔离.降级策略.熔断技术. 在高并发访问下,系统所依赖的服务的稳定性对系统的影响非常大,依赖有很多不可控的因素,比如网络连接变慢,资源突然繁忙,暂时不可用,服务脱机等.我们要构建稳定.可靠的分布式系统,就必须要有这样一套容错方法. 本文主要讨论线程隔离技术. 为什么要做线程隔离 比如我们现在有3个业务调用分别是查询订单.查询商品.查询用户,且这三个业务请求都是依赖第三方服务-订单服务.商品服

Thread线程join方法自我理解

thread.join():等待thread线程运行终止,指的是main-thread(main线程)必须等待thread线程运行结束,才能继续thread.join();后面的代码 thread.join(long time):线程thread等待time时间之后,main-thread可以执行,注意time时间后,线程thread没有执行完,main-thread也可以运行 注意:上面2个方法必须在线程是alive的时候,才有这样的效果,否则不会有. join()方法源码是有调用wait()

Process进程 ; Thread线程

<> 前台线程和后台线程 InvokeHelper:跨线程访问/修改主界面控件方法.属性 C#线程用法及跨线程访问 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; namespace 进程Process { /// <summary> /// Process类是一个非静态类.它里面包含静态成员和非静态成员.静

boost::thread 线程锁

1.boost锁的概述: boost库中提供了mutex类与lock类,通过组合可以轻易的构建读写锁与互斥锁. 2.mutex对象类(主要有两种): 1.boost::mutex(独占互斥类) --> 有lock和unlock方法 2.boost::shared_mutex(共享互斥类) --> 有lock和unlock方法 And shared_lock和shared_unlock方法 3. lock模板类: 1.boost::unique_lock<T>(独占锁) : uniq

Thread 线程池中可用的线程数量

GetAvaliableThread(out workerThreadCount,out iocompletedThreadCount)   函数居然一次返回了两个变量.线程池里的线程按照公用被分成了两大类:工作线程和IO线程,或者IO完成线程,前者用于执行普通的操作,后者专用于异步IO,比如文件和网络请求,注意,分类并不说明两种线程本身有差别,线程就是线程,是一种执行单元,从本质上来讲都是一样的,线程池这样分类 Thread 线程池中可用的线程数量

Thread线程的方法用法,有代码例子,简单易懂

/** *  程序 :  *      就是指我们写的保存硬盘当中的静态文件,叫程序 *  进程 :   *      就是程序被加载进内存,准备或者正在运行时,就叫进程 *  线程 :  *      就是程序中不同的执行路径 * *  线程 :  *      当我们程序开始执行的时候,就是java中main()方法开始执行,在栈内存中开辟main()栈帧的时候,就是开启了一个线程 *      一个线程就是一个栈及其里面的链式栈帧,一个栈帧就对应一个方法. *   */☆☆☆☆ 重点 ☆☆

Handler和Thread线程

大家都知道,在PC上的应用程序当需要进行一些复杂的数据操作,但不需要界面UI的时候,我们会为应用程序专门写一个线程去执行这些复杂的数据操作.通过线程,可以执行例如:数据处理.数据下载等比较耗时的操作,同时对用户的界面不会产生影响.在Android应用程序开发中,同样会遇到这样的问题.当我们需要访问网络,从网上下载数据并显示在我们的UI上时,就会启动后台线程去下载数据,下载线程执行完成后将结果返回给主用户界面线程. 对于线程的控制,我们将介绍一个Handler类,使用该类可以对运行在不同线程中的多

C++11之thread线程

今天由于项目需求(其实是某门课的一个大作业,不好意思说出口啊...),想要使用多线程.相信大家一般用的是linux上的POSIX C或windows上的线程库,然而这些线程库以来于特定系统,并不“标准”.2011年发布的C++11标准中提供了并发执行的相关操作: C++11 新标准中引入了四个头文件来支持多线程编程,他们分别是<atomic> ,<thread>,<mutex>,<condition_variable>和<future>. <

android操作线程各种方法解析

(一)刚开始学习android的时候我是这么写的 1 new Thread( new Runnable() { public void run() { myView.invalidate(); } }).start(); 后来看到别的博客说这种违反android单线程模型 本人不理解非要刨根问题 那么它是怎么违反单线程模型的呢? 百度了一下找到了原因 如下 一个 Android 程序开始运行时,就有一个主线程Main Thread被创建.该线程主要负责UI界面的显示.更新和控件交互,所以又叫UI