多线程01
作者:互联网
一、并行和并发:
并行:多个任务在同一时刻同时执行。
并发:多个任务顺序执行,不是同时。
二、进程和线程:
进程是系统分配资源的最小单位,线程是cpu执行任务的最小单位。
对于单核CPU而言,同一时刻只能执行一个线程。每隔一定时间会切换线程(可能是同一个进程的线程,也可能是另外一个进程的线程,如果是其它进程的线程)。
在单核CPU上实现的多线程其实是“假”的多线程,CPU同一时刻只能执行,只不过CPU切换任务的速度很快,所以你感觉是同时执行了多个任务,即实现了多线程。
在单核CPU上,无论是线程还是进程,都只能并发执行,多核CUP上有可能实现并行执行。
三、多线程
下面用一个最简单的多线程例子说明。
C++11之前创建多线程的函数有2个:_beginthreadex、CreateThread
前者是C++库函数,后者是Windows API。我们使用_beginthreadex。
int main() { for (int i = 0; i < 5; i++) { cout<<"1234567890------"<< i<<endl; } system("pause"); return 0; }
上述程序只有一个进程,mian函数就是这个进程的主线程,打印结果,是顺序执行,顺序打印。
现在给它添加一个子线程:
//线程函数 unsigned __stdcall ThreadProc( void * lpParameter) { int* p = (int*)lpParameter; for (int i = 0; i < *p; i++) { cout<<"abcdefghij------"<< i<<endl; } return 0; } int main() { unsigned nThreadID = 0 ; int n = 5; HANDLE hThread = (HANDLE)_beginthreadex( NULL, 0, &ThreadProc, (LPVOID)&n, 0, &nThreadID ); CloseHandle(hThread); for (int i = 0; i < 5; i++) { cout<<"1234567890------"<< i<<endl; } system("pause"); return 0; }
打印结果如下。可以看到,虽然代码中,主线程的打印部分是写在子线程的后面的,但结果是主线程的打印内容先出来了。
我们再在主线程和子线程中分别加上一个Sleep,如下:
//线程函数 unsigned __stdcall ThreadProc( void * lpParameter) { int* p = (int*)lpParameter; for (int i = 0; i < *p; i++) { Sleep(10); cout<<"abcdefghij------"<< i<<endl; } return 0; } int main() { unsigned nThreadID = 0 ; int n = 5; HANDLE hThread = (HANDLE)_beginthreadex( NULL, 0, &ThreadProc, (LPVOID)&n, 0, &nThreadID ); CloseHandle(hThread); for (int i = 0; i < 5; i++) { Sleep(10); cout<<"1234567890------"<< i<<endl; } system("pause"); return 0; }
打印结果如下。可以发现顺序又变了,而且相互影响,没有规律。
四、线程安全
上面的最后一个例子,可以发现最后的打印结果没有规律,不可预见,就称之为线程不安全,在实际项目中这样简单地使用多线程代码肯定是不行的。
线程不安全的原因通常是共享了资源,解决方法是使用加锁来规避。
锁的核心功能是多个线程访问同一个资源,保证同一时刻只有一个线程能使用该资源,对该资源有独占访问权。
C++ 11 封装了类mutex,帮我们完成,直接用就行了。
五、使用锁mutex
mutex mutex1 ; unsigned __stdcall ThreadProc( void * lpParameter) { int* p = (int*)lpParameter; for (int i = 0; i < *p; i++) { mutex1.lock(); Sleep(10); cout<<"abcdefghij------"<< i<<endl; mutex1.unlock(); } return 0; } int main() { unsigned nThreadID = 0 ; int n = 5; HANDLE hThread = (HANDLE)_beginthreadex( NULL, 0, &ThreadProc, (LPVOID)&n, 0, &nThreadID ); CloseHandle(hThread); for (int i = 0; i < 5; i++) { mutex1.lock(); Sleep(10); cout<<"1234567890------"<< i<<endl; mutex1.unlock(); } system("pause"); return 0; }
结果如下:
其实 最后一行 system("pause"); 也使用了cout,完整的写法应该在它的前后也加上锁。
否则,如果将Sleep的参数改大,比如我的电脑上,将其改为Sleep(5000),可能出现如下结果:
六、使用C++11开发多线程
C++11不仅仅有线程锁的封装,也提供了线程的封装 std::thread。
在C++11之前,我们只能使用windows的api来实现多线程,现在抛弃前面创建多线程的那一套吧,直接使用封装好的 std::thread 类。
标签:01,cout,int,C++,线程,lpParameter,多线程 来源: https://www.cnblogs.com/hosseini/p/15162745.html