1.操作系统如何实现原子性
在单处理器,单核,运行多线程的情况下,我们不使用线程同步工具,
我们会出现,线程之间会互相抢夺,临界区的资源,造成数据不符合我们预期的结果,
后面再说解决办法,那么我们怎么帮助实现原子性
1 屏蔽中断,不让线程之间切换,让它完成再切换
2 底层硬件自旋锁,也是不让切换的思路
在多处理器,多核,运行多线程的情况下,除了上面两点,我们该如何保持原子性呢?
让我们先了解一下 多核 cpu 之间是如何通信的:
如图,通过CPU总线 进行数据交换
问题 1
因为我们每个核心都在执行任务,当我们执行任务时,都在对同一个数据进行修改
那么到底用 哪一个数据呢?
问题 2
当 我们 使用缓存时,数据在缓存 与 磁盘上不一致时,CPU 该如何保持呢?
一致性协议,就是解决这种问题,
所以 当我们 想使用 具有 原子性 的变量时,使用 修改(modified) 和 独占(exclusive) 的数据
2.在c++中如何实现线程同步
1.使用 条件变量和锁
写一个例子:
三个线程轮流 输出 1 2 3 到 100
std::condition_variable cond;
std::mutex mtu;
int nums = 1;
void fun1()
{
while (nums <= 100)
{
{
std::unique_lock<std::mutex> lock(mtu);
if (nums % 3 == 1)
{
cout << "nums 1:" << nums << endl;
nums++;
cond.notify_all();
}
else
{
cond.wait(lock);
}
}
}
cond.notify_all();
}
void fun2()
{
while (nums <= 100)
{
{
std::unique_lock<std::mutex> lock(mtu);
if (nums % 3 == 2)
{
cout << "nums 2:" << nums << endl;
nums++;
cond.notify_all();
}
else
{
cond.wait(lock);
}
}
}
cond.notify_all();
}
void fun3()
{
while (nums <= 100)
{
{
std::unique_lock<std::mutex> lock(mtu);
if (nums % 3 == 0)
{
cout << "nums 3:" << nums << endl;
nums++;
cond.notify_all();
}
else
{
cond.wait(lock);
}
}
}
cond.notify_all();
}
int main()
{
std::thread t1(fun1);
std::thread t2(fun2);
std::thread t3(fun3);
t1.join();
t2.join();
t3.join();
cout << "打印完毕" << endl;
return 0;
}
2.使用atomic
std::atomic<int> nums(1);
void print_nums(int remainder)
{
while (nums <= 100)
{
int current_nums;
do
{
current_nums = nums.load();
} while (current_nums % 3 != remainder && !nums.compare_exchange_weak(current_nums, current_nums + 1));
if (current_nums <= 100)
{
std::cout << "nums " << remainder + 1 << ":" << current_nums << std::endl;
}
}
}
int main()
{
std::thread t1(print_nums, 1);
std::thread t2(print_nums, 2);
std::thread t3(print_nums, 0);
t1.join();
t2.join();
t3.join();
std::cout << "打印完毕" << std::endl;
return 0;
}