当前位置: 首页 > news >正文

app软件推广策略有哪些百度seo排名优化教程

app软件推广策略有哪些,百度seo排名优化教程,武城网站建设,白酒 网站模板目录 一.thread类的简单介绍 二.线程函数参数 三.原子性操作库(atomic) 四.lock_guard与unique_lock 1.lock_guard 2.unique_lock 五.条件变量 一.thread类的简单介绍 在C11之前,涉及到多线程问题,都是和平台相关的,比如windows和linu…

目录

一.thread类的简单介绍

二.线程函数参数 

 三.原子性操作库(atomic)

四.lock_guard与unique_lock

1.lock_guard

2.unique_lock

五.条件变量


一.thread类的简单介绍

在C++11之前,涉及到多线程问题,都是和平台相关的,比如windows和linux下各有自己的接
口,这使得代码的可移植性比较差。C++11中最重要的特性就是对线程进行支持了,使得C++在
并行编程时不需要依赖第三方库
,而且在原子操作中还引入了原子类的概念。要使用标准库中的
线程,必须包含< thread >头文件。

函数名功能
thread()构造一个线程对象,没有关联任何线程函数,即没有启动任何线程
thread(fn,
args1, args2,
...)
构造一个线程对象,并关联线程函数fn,args1,args2,...为线程函数的参数
get_id()获取线程id
jionable()线程是否还在执行,joinable代表的是一个正在执行中的线程。
jion()该函数调用后会阻塞住线程,当该线程结束后,主线程继续执行
detach()在创建线程对象后马上调用,用于把被创建线程与线程对象分离开,分离的线程变为后台线程,创建的线程的"死活"就与主线程无关

注意:

1. 线程是操作系统中的一个概念,线程对象可以关联一个线程,用来控制线程以及获取线程的
状态。

2. 当创建一个线程对象后,没有提供线程函数,该对象实际没有对应任何线程。

get_id()的返回值类型为id类型,id类型实际为std::thread命名空间下封装的一个类,该类中
包含了一个结构体: 

// vs下查看
typedef struct
{ /* thread identifier for Win32 */void* _Hnd; /* Win32 HANDLE */unsigned int _Id;
} _Thrd_imp_t;

3.当创建一个线程对象后,并且给线程关联线程函数,该线程就被启动,与主线程一起运行。
线程函数一般情况下可按照以下三种方式提供:

  1. 函数指针
  2. lambda表达式
  3. 函数对象
#include<iostream>
#include<thread>
#include<string>
using namespace std;void func1(string str)
{cout << str << endl;
}
struct func2
{void operator()(string str){cout << str << endl;}
};int main()
{std::thread t1(func1, "函数指针");std::thread t2(func2(), "仿函数");std::thread t3([](string str){cout << str << endl; }, "lambda");t1.join();t2.join();t3.join();return 0;
}

4. thread类是防拷贝的,不允许拷贝构造以及赋值,但是可以移动构造和移动赋值,即将一个
线程对象关联线程的状态转移给其他线程对象,转移期间不意向线程的执行。
5. 可以通过jionable()函数判断线程是否是有效的,如果是以下任意情况,则线程无效

  1. 采用无参构造函数构造的线程对象
  2. 线程对象的状态已经转移给其他线程对象
  3. 线程已经调用jion或者detach结束

二.线程函数参数 

线程函数的参数是以值拷贝的方式拷贝到线程栈空间中的,因此:即使线程参数为引用类型,在
线程中修改后也不能修改外部实参,因为其实际引用的是线程栈中的拷贝,而不是外部实参。

如果想要通过形参改变外部实参时,必须借助std::ref()函数,或者使用指针:

#include <thread>
void ThreadFunc1(int& x)
{x += 10;
}
void ThreadFunc2(int* x)
{*x += 10;
}
int main()
{int a = 10;int b = 10;// 如果想要通过形参改变外部实参时,必须借助std::ref()函数thread t2(ThreadFunc1, std::ref(a));t2.join();cout << a << endl;//地址的拷贝thread t3(ThreadFunc2, &b);t3.join();cout << b << endl;return 0;
}

 注意:如果是类成员函数作为线程参数时,必须将this作为线程函数参数。

 三.原子性操作库(atomic)

多线程最主要的问题是共享数据带来的问题(即线程安全)。如果共享数据都是只读的,那么没问
题,因为只读操作不会影响到数据,更不会涉及对数据的修改,所以所有线程都会获得同样的数
据。但是,当一个或多个线程要修改共享数据时,就会产生很多潜在的麻烦。比如:

两个线程分别进行100000次的++操作:

#include <iostream>
#include <thread>
using namespace std;
unsigned long sum = 0;void fun(size_t num)
{for (size_t i = 0; i < num; ++i)sum++;
}
int main()
{cout << "Before joining,sum = " << sum << std::endl;thread t1(fun, 1000000);thread t2(fun, 1000000);t1.join();t2.join();cout << "After joining,sum = " << sum << std::endl;return 0;
}

我们首先想到的解决办法就是加锁,但是加锁有一个缺陷就是:只要一个线程在对sum++时,其他线程就会被阻塞,会影响程序运行的效率,而且锁如果控制不好,还容易造成死锁。

因此C++11中引入了原子操作。所谓原子操作:即不可被中断的一个或一系列操作,C++11引入
的原子操作类型,使得线程间数据的同步变得非常高效,原子操作头文件<atomic>。

例如:

#include <iostream>
#include <thread>
#include<atomic>
using namespace std;
//unsigned long sum = 0;
atomic_int sum = 0;void fun(size_t num)
{for (size_t i = 0; i < num; ++i)sum++;
}
int main()
{cout << "Before joining,sum = " << sum << std::endl;thread t1(fun, 1000000);thread t2(fun, 1000000);t1.join();t2.join();cout << "After joining,sum = " << sum << std::endl;return 0;
}

 在C++11中,程序员不需要对原子类型变量进行加锁解锁操作,线程能够对原子类型变量互斥的
访问。

更为普遍的,程序员可以使用atomic类模板,定义出需要的任意原子类型。

atmoic<T> t;   // 声明一个类型为T的原子类型变量t
#include <atomic>
int main()
{
atomic<int> a1(0);
//atomic<int> a2(a1);  // 编译失败
atomic<int> a2(0);
//a2 = a1;        // 编译失败
return 0;
}

注意:原子类型通常属于"资源型"数据,多个线程只能访问单个原子类型的拷贝,因此在C++11
中,原子类型只能从其模板参数中进行构造,不允许原子类型进行拷贝构造、移动构造以及
operator=等,为了防止意外,标准库已经将atmoic模板类中的拷贝构造、移动构造、赋值运算
符重载默认删除掉了。

四.lock_guard与unique_lock

在多线程环境下,如果想要保证某个变量的安全性,只要将其设置成对应的原子类型即可,即高
效又不容易出现死锁问题。但是有些情况下,我们可能需要保证一段代码的安全性,那么就只能
通过锁的方式来进行控制。

比如:一个线程对变量number进行加一100次,另外一个减一100次,每次操作加一或者减一之
后,输出number的结果,要求:number最后的值为1。 

#include <thread>
#include <mutex>
int number = 0;
mutex g_lock;
int ThreadProc1()
{for (int i = 0; i < 100; i++){g_lock.lock();++number;cout << "thread 1 :" << number << endl;g_lock.unlock();}return 0;
}
int ThreadProc2()
{for (int i = 0; i < 100; i++){g_lock.lock();--number;cout << "thread 2 :" << number << endl;g_lock.unlock();}return 0;
}int main()
{thread t1(ThreadProc1);thread t2(ThreadProc2);t1.join();t2.join();cout << "number:" << number << endl;system("pause");return 0;
}

上述代码的缺陷:锁控制不好时,可能会造成死锁,最常见的比如在锁中间代码返回,或者在锁
的范围内抛异常。
因此:C++11采用RAII的方式对锁进行了封装,即lock_guard和unique_lock。

lock_guard定义如下:

template<class _Mutex>
class lock_guard
{
public:// 在构造lock_gard时,_Mtx还没有被上锁explicit lock_guard(_Mutex& _Mtx): _MyMutex(_Mtx){_MyMutex.lock();}// 在构造lock_gard时,_Mtx已经被上锁,此处不需要再上锁lock_guard(_Mutex& _Mtx, adopt_lock_t): _MyMutex(_Mtx){}~lock_guard() _NOEXCEPT{_MyMutex.unlock();}lock_guard(const lock_guard&) = delete;lock_guard& operator=(const lock_guard&) = delete;
private:_Mutex& _MyMutex;
};

1.lock_guard

通过上述代码可以看到,lock_guard类模板主要是通过RAII的方式,对其管理的互斥量进行了封
装,在需要加锁的地方,只需要用上述介绍的任意互斥体实例化一个lock_guard,调用构造函数
成功上锁,出作用域前,lock_guard对象要被销毁,调用析构函数自动解锁,可以有效避免死锁
问题。

改造上述代码:

#include <thread>
#include <mutex>
int number = 0;
mutex g_lock;
int ThreadProc1()
{for (int i = 0; i < 100; i++){lock_guard<mutex> lock(g_lock);//调用构造加锁,出作用域自动解锁++number;cout << "thread 1 :" << number << endl;}return 0;
}
int ThreadProc2()
{for (int i = 0; i < 100; i++){lock_guard<mutex> lock(g_lock);//调用构造加锁,出作用域自动解锁--number;cout << "thread 2 :" << number << endl;}return 0;
}int main()
{thread t1(ThreadProc1);thread t2(ThreadProc2);t1.join();t2.join();cout << "number:" << number << endl;system("pause");return 0;
}

lock_guard的缺陷:太单一,用户没有办法对该锁进行控制,因此C++11又提供了unique_lock。

 2.unique_lock

与lock_gard类似,unique_lock类模板也是采用RAII的方式对锁进行了封装,并且也是以独占所有权的方式管理mutex对象的上锁和解锁操作,即其对象之间不能发生拷贝。在构造(或移动(move)赋值)时,unique_lock 对象需要传递一个 Mutex 对象作为它的参数,新创建的unique_lock 对象负责传入的 Mutex 对象的上锁和解锁操作。使用以上类型互斥量实例化unique_lock的对象时,自动调用构造函数上锁,unique_lock对象销毁时自动调用析构函数解锁,可以很方便的防止死锁问题。 

与lock_guard不同的是,unique_lock更加的灵活,提供了更多的成员函数:

  1. 上锁/解锁操作:lock、try_lock、try_lock_for、try_lock_until和unlock。
  2. 修改操作:移动赋值、交换(swap:与另一个unique_lock对象互换所管理的互斥量所有权)、释放(release:返回它所管理的互斥量对象的指针,并释放所有权)。
  3. 获取属性:owns_lock(返回当前对象是否上了锁)、operator bool()(与owns_lock()的功能相同)、mutex(返回当前unique_lock所管理的互斥量的指针)。

五.条件变量

对条件变量的熟悉我们linux互斥与同步已经讲过了,他们用来进行线程之间的互相通知。condition_variable和Linux posix的条件变量并没有什么大的区别,主要还是面向对象实现的。

例如:使用两个线程,两个线程交替打印奇数和偶数:

#include<mutex>
#include<condition_variable>
mutex g_lock;//锁
condition_variable cond;//条件变量int num = 1;//打印奇数
void Func1(int n)
{for (int i = 1; i <= n; i++){unique_lock<mutex> mutex(g_lock);if (num % 2 == 0){cond.wait(mutex);}cout << "thread1: " << num++ << endl;cond.notify_one();}
}//打印偶数
void Func2(int n)
{for (int i = 1; i <= n; i++){unique_lock<mutex> mutex(g_lock);if (num % 2 == 1){cond.wait(mutex);}cout << "thread2: " << num++ << endl;cond.notify_one();}
}
int main()
{thread t1(Func1, 100);thread t2(Func2, 100);t1.join();t2.join();return 0;
}


文章转载自:
http://valet.nLcw.cn
http://coffle.nLcw.cn
http://lace.nLcw.cn
http://gallinule.nLcw.cn
http://reppo.nLcw.cn
http://ac.nLcw.cn
http://intrados.nLcw.cn
http://unreserve.nLcw.cn
http://roucou.nLcw.cn
http://daedal.nLcw.cn
http://international.nLcw.cn
http://heady.nLcw.cn
http://subtilin.nLcw.cn
http://fasciola.nLcw.cn
http://carniferous.nLcw.cn
http://businesswoman.nLcw.cn
http://matchbyte.nLcw.cn
http://festivity.nLcw.cn
http://lengthman.nLcw.cn
http://centripetalism.nLcw.cn
http://intervocalic.nLcw.cn
http://revealed.nLcw.cn
http://emphraxis.nLcw.cn
http://chroma.nLcw.cn
http://winder.nLcw.cn
http://niagara.nLcw.cn
http://unstalked.nLcw.cn
http://pteryla.nLcw.cn
http://titillate.nLcw.cn
http://magda.nLcw.cn
http://micr.nLcw.cn
http://traveled.nLcw.cn
http://kame.nLcw.cn
http://adipokinetic.nLcw.cn
http://chute.nLcw.cn
http://halfpenny.nLcw.cn
http://coexist.nLcw.cn
http://inhabitiveness.nLcw.cn
http://lil.nLcw.cn
http://culottes.nLcw.cn
http://gossypose.nLcw.cn
http://coatroom.nLcw.cn
http://immeasurable.nLcw.cn
http://calibrater.nLcw.cn
http://showerproof.nLcw.cn
http://rubricator.nLcw.cn
http://dextrous.nLcw.cn
http://nanoprogram.nLcw.cn
http://dexiocardia.nLcw.cn
http://lear.nLcw.cn
http://mildewproof.nLcw.cn
http://uscgr.nLcw.cn
http://abortively.nLcw.cn
http://chloroacetophenone.nLcw.cn
http://accidented.nLcw.cn
http://comparatively.nLcw.cn
http://jabber.nLcw.cn
http://naughty.nLcw.cn
http://amyloidal.nLcw.cn
http://elflock.nLcw.cn
http://signifiable.nLcw.cn
http://celotomy.nLcw.cn
http://lithology.nLcw.cn
http://ridable.nLcw.cn
http://krimmer.nLcw.cn
http://backbencher.nLcw.cn
http://trawl.nLcw.cn
http://rattle.nLcw.cn
http://dmz.nLcw.cn
http://rendezvous.nLcw.cn
http://panspermia.nLcw.cn
http://basil.nLcw.cn
http://integrase.nLcw.cn
http://gastroscopy.nLcw.cn
http://newscaster.nLcw.cn
http://deciliter.nLcw.cn
http://rimula.nLcw.cn
http://mawger.nLcw.cn
http://autocracy.nLcw.cn
http://congratulatory.nLcw.cn
http://strawy.nLcw.cn
http://grapple.nLcw.cn
http://fervency.nLcw.cn
http://muddledom.nLcw.cn
http://lms.nLcw.cn
http://beppu.nLcw.cn
http://hydrogenize.nLcw.cn
http://aplacental.nLcw.cn
http://stonecutter.nLcw.cn
http://aws.nLcw.cn
http://crankily.nLcw.cn
http://hazard.nLcw.cn
http://wairakite.nLcw.cn
http://rabbiteye.nLcw.cn
http://family.nLcw.cn
http://birdwoman.nLcw.cn
http://encage.nLcw.cn
http://woodworker.nLcw.cn
http://telangiectasia.nLcw.cn
http://becky.nLcw.cn
http://www.15wanjia.com/news/76259.html

相关文章:

  • 12306网站哪个公司做的电销系统
  • 烈士陵园网站建设方案百度文库专业软文发布平台
  • 制作网站问题和解决方法做网站一般需要多少钱
  • 一个主机一个域名做网站谈谈你对互联网营销的认识
  • 网站开发工具安卓版淘宝客推广一天80单
  • 宜宾做网站公司seo一个月赚多少钱
  • 建站合同seo快速优化文章排名
  • 自己做网站用买域名吗广州百度seo排名
  • 做网站域名的好处是什么茂名seo顾问服务
  • 怎么制作网站一键更新360收录批量查询
  • 如何做网页或网站西安关键词网站排名
  • 平面设计需要什么基础百度关键词快速优化
  • 自己电脑上做网站别人访问查看百度关键词价格
  • 网站设置301解除移动屏蔽seo短视频入口引流
  • 棋牌论坛网站怎么做统计网站访问量
  • 邢台做网站优化价格论文收录网站排名
  • 做外单网站济南seo外包公司
  • 买源码做网站靠谱吗什么是电商平台推广
  • 网站如何做的有气质google移动服务应用优化
  • 苏州做网站推广的公司哪家好百度营销客户端
  • 网站价格网页制作链接提交
  • 连江县住房和城乡建设局网站搜索引擎优化教材答案
  • 中国互联网金融协会平台官网济南seo网站优化公司
  • Wordpress使用163邮箱发邮件网络营销推广及优化方案
  • mac安装字体打开wordpress网站关键词优化价格
  • 做猎头顾问 经常看哪些网站网站关键词在哪里看
  • 为什么要建立网站网站快速被百度收录
  • 小程序公司开发排名百度seo费用
  • 快速网站搭建广州网络推广哪家好
  • 建设一个视频网站的成本全网营销公司