1.写一个c程序辨别系统是64位 or 32位
void* number = 0; printf("%d\n",sizeof(&number));
输出8就是64位 输出4就是32位的 根据逻辑地址判断的
2. i++ 是否原子操作?并解释为什么?
原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。则其肯定不是原子操作,i++做了三次指令操作,两次内存访问,第一次,从内存中读取i变量的值到CPU的寄存器,第二次在寄存器中的i自增1,第三次将寄存器中的值写入内存。这三次指令操作中任意两次如果同时执行的话,都会造成结果的差异性。
在多核CPU的复杂内存操作中,处理器提供了总线锁和缓存锁两个机制来保证原子性,可以通过处理器提供的很多LOCK前缀的指令来实现。
思考:a =2是否为原子操作。a = b;是否为原子操作?
C++ 对原子操作的支持:
在 C++ 98/03 标准中,如果想对整型变量进行原子操作,要么利用操作系统提供的相关原子操作 API,要么利用对应操作系统提供的锁对象来对变量进行保护,无论是哪种方式,编写的代码都无法实现跨平台操作,例如上一小介绍的 Interlocked 系列API代码仅能运行于 Windows系统,无法移植到 Linux系统。C++11 新标准发布以后,改变了这种困境,新标准提供了对整型变量原子操作的相关库,即 std::atomic ,这是一个模板类型:
template<class T>
struct atomic;
读者可以传入具体的整型类型(如bool、char、short、int、uint等)对模板进行实例化,实际上stl库也提供了这些实例化的模板类型:
类型别名 定义
std::atomic_bool std::atomic<bool>
std::atomic_char std::atomic<char>
#include <atomic>
#include <stdio.h>
int main()
{
std::atomic<int> value = 99;
printf("%d\n", (int)value);
//自增1,原子操作
value++;
printf("%d\n", (int)value);
return 0;
}
代码仅仅做了一点简单的改动,这段代码在 Windows 平台上运行良好,但是在 Linux 平台上会无法编译通过(这里指的是在支持 C++11 语法的 g++ 编译器中编译),提示错误是:
error: use of deleted function ‘std::atomic<int>::atomic(const std::atomic<int>&)’
产生这个错误的原因是:std::atomic<int> value = 99; 这一行代码调用的是 std::atomic 的拷贝构造函数,对于 int 型,其形式一般如下:
std::atomic<int>::atomic(const std::atomic<int>& rhs);
而根据 C++11 的规范,这个拷贝构造函数是默认使用 =delete 语法禁止编译器生成的,g++ 遵循了这个标准:https://zh.cppreference.com/w/cpp/atomic/atomic/operator%3D
atomic& operator=( const atomic& ) = delete;
所以 Linux 平台上编译器会提示错误,而 Windows 的 VC++ 编译器没有遵循这个规范。而对于代码:
value = 99;
修改为:std::atomic<int> g_count(2);
g++ 和 VC++ 同时实现规范中的:
T operator=( T desired )
因此,如果你想利用 C++11 提供的 std::atomic 库编写跨平台的代码,在使用 std::atomic 提供的方法时建议参考官方 std::atomic 提供的接口说明来使用,而不是想当然地认为一个方法在此平台上可以运行,在另外一个平台也能有相同的行为,避免出现上面说的这种情形。
另外,需要说明的是,上述代码中之所以可以对 value 进行自增(++)操作是因为 std::atomic 类内部重载了 operator++ 运算符,除此以外, std::atomic 提供了大量有用的方法,你可能会觉得这些方法似曾相识:
方法名 方法说明
operator= 存储值于原子对象
store 原子地以非原子对象替换原子对象的值
load 原子地获得原子对象的值
# 总结
0. 一般的CPU 操作数的话,都是从内存到寄存器,再从寄存器到内存。由于有多个步骤,存在被打断的可能,所以就不是原子的。
1. 原子操作是值在汇编指令时只有一条,这样在多线程操作同一个数的时候就不会出现 抢占CPU 时间片而出现的问题了。
2. 目前有的处理器从硬件层面可以实现原子操作了。
3. 原子操作在定义时std::atomic<int> g_count = 2;会报错,需要修改为std::atomic<int> g_count(2);
4. 原子操作的各种操作比如++,--这些可以直接用的原因是C++11能保证这些操作也是原子的。
3.说出你所知道的各类linux系统的各类同步机制(重点),什么是死锁?如何避免死锁(每个技术面试官必问)
什么是同步机制?同步机制是一种操作系统提供的机制,用于协调多个进程或线程之间的访问共享资源,防止出现竞态条件和死锁等问题
Linux中常用的同步机制有哪些?Linux中常用的同步机制包括互斥锁、读写锁、自旋锁、信号量、条件变量等。
死锁就是几个进程申请资源,出现了循环等待的情况!
避免死锁的方法:
1)资源是互斥的
2)不可抢占
3)占有且申请
4)循环等待
12 线程的五种状态