原子锁
现象:
(1)单线程无锁速度最快,但应用场合受限;
(2)多线程无锁速度第二快,但结果不对,未保护临界代码段;
(3)多线程原子锁第三快,且结果正确;
(4)多线程互斥量较慢,慢与原子锁近10倍,结果正确;
(5)多线程自旋锁最慢,慢与原子锁30倍,结果正确。
结论:原子锁速度最快,互斥量和自旋锁都用保护多线程共享资源。
自旋锁是一种非阻塞锁,也就是说,如果某线程需要获取自旋锁,但该锁已经被其他线程占用时,该线程不会被挂起,而是在不断的消耗cpu的时间,不停的试图获取自旋锁。
互斥量是阻塞锁,当某线程无法获取互斥量时,该线程会被直接挂起,该线程不再消耗CPU时间,当其他线程释放互斥量后,操作系统会激活那个被挂起的线程,让其投入运行。
在多处理器环境中对持有锁时间较短的程序来说使用自旋锁代替一般的互斥锁往往能提高程序的性能,但是本代码无该效果。
#include <iOStream>
#include <atomic>
#include <mutex>
#include <thread>
#include <vector>
class spin_mutex {
std::atomic<bool> flag = ATOMIC_VAR_INIT(false);
public:
spin_mutex() = default;
spin_mutex(const spin_mutex&) = delete;
spin_mutex& operator= (const spin_mutex&) = delete;
void lock() {
bool expected = false;
while (!flag.compare_exchange_strong(expected, true))
expected = false;
}
void unlock() {
flag.store(false);
}
};
long size = 1000000;
long total = 0;
std::atomic_long total2(0);
std::mutex m;
spin_mutex lock;
void thread_click()
{
for (int i = 0; i < size; ++i)
{
++total;
}
}
void mutex_click()
{
for (int i = 0; i < size; ++i)
{
m.lock();
++total;
m.unlock();
}
}
void atomic_click()
{
for (int i = 0; i < size; ++i)
{
++total2;
}
}
void spinlock_click()
{
for (int i = 0; i < size; ++i)
{
lock.lock();
++total;
lock.unlock();
}
}
int main()
{
int thnum = 100;
std::vector<std::thread> threads(thnum);
clock_t start, end;
total = 0;
start = clock();
for (int i = 0; i < size * thnum; i++) {
++total;
}
end = clock();
std::cout << "single thread result: " << total << std::endl;
std::cout << "single thread time: " << end - start << std::endl;
total = 0;
start = clock();
for (int i = 0; i < thnum; ++i) {
threads[i] = std::thread(thread_click);
}
for (int i = 0; i < thnum; ++i) {
threads[i].join();
}
end = clock();
std::cout << "multi thread no mutex result: " << total << std::endl;
std::cout << "multi thread no mutex time: " << end - start << std::endl;
total = 0;
start = clock();
for (int i = 0; i < thnum; ++i) {
threads[i] = std::thread(atomic_click);
}
for (int i = 0; i < thnum; ++i) {
threads[i].join();
}
end = clock();
std::cout << "multi thread atomic result: " << total2 << std::endl;
std::cout << "multi thread atomic time: " << end - start << std::endl;
total = 0;
start = clock();
for (int i = 0; i < thnum; ++i) {
threads[i] = std::thread(mutex_click);
}
for (int i = 0; i < thnum; ++i) {
threads[i].join();
}
end = clock();
std::cout << "multi thread mutex result: " << total << std::endl;
std::cout << "multi thread mutex time: " << end - start << std::endl;
total = 0;
start = clock();
for (int i = 0; i < thnum; ++i) {
threads[i] = std::thread(spinlock_click);
}
for (int i = 0; i < thnum; ++i) {
threads[i].join();
}
end = clock();
std::cout << "spin lock result: " << total << std::endl;
std::cout << "spin lock time: " << end - start << std::endl;
getchar();
return 0;
}
/*
single thread result: 100000000
single thread time: 231
multi thread no mutex result: 11501106
multi thread no mutex time: 261
multi thread atomic result: 100000000
multi thread atomic time: 1882
multi thread mutex result: 100000000
multi thread mutex time: 16882
spin lock result: 100000000
spin lock time: 45063
*/
相关阅读
stdafx是预编译头文件,在其中包含的头文件之外第一次编译时编译,之后若不修改,不会再编译这些头文件,加快了编译的速度。targetver定
以前我这样初始化一个数组,并自我感觉良好:int a[5] = { 0 }; // 全部初始化为0这种简单的写法让我非常爽,于是我又想把数组全部初
一、有三个API函数可以运行可执行文件WinExec、ShellExecute和CreateProcess。 1.CreateProcess因为使用复杂,比较少用。2.WinExec
使用C/C++编程时,常使用ZeroMemory、memset或 “={0}”来对结构体对象进行初始化或清零。然而这三种方式都有各自的特点,使用时需谨
[下载篇]VC++ 2010 Express 学生版 NCRE考试编译器
网盘下载地址[无密码] 2018年 NCRE考试 C++\C语言考试 改为 VC++ 2010 Express !!!!!!! 如果需要,请下载! 6VPJ7-H3CXH-HBTPT-X4T74-3YVY