基础
C++程序中的所有数据都是由对象(objects)构成,一个对象都会存储在一个或多个内存位置上。
位域:虽然相邻位域中是不同的对象,但仍视其为相同的内存位置
四个原则:
- 每一个变量都是一个对象,包括作为其成员变量的对象。
- 每个对象至少占有一个内存位置。
- 基本类型都有确定的内存位置(无论类型大小如何,即使他们是相邻的,或是数组的一部分)。
- 相邻位域是相同内存中的一部分。
内存位置和并发关系
当两个线程访问不同(separate)的内存位置时,不会存在任何问题;当两个线程访问同一(same)个内存位置,就要小心。读没有问题,如果存在对内存位置上的数据进行修改,就有可能产生条件竞争。
避免条件竞争
- 使用互斥量
- 原子操作
如果不去规定两个不同线程对同一内存地址访问的顺序,那么访问就不是原子的;并且,当两个线程都是“作者”时,就会产生数据竞争和未定义行为。
未定义的行为是C++中最黑暗的角落。根据语言的标准,一旦应用中有任何未定义的行为,就很难预料会发生什么事情;因为,未定义行为是难以预料的。我就知道一个未定义行为的特定实例,让某人的显示器起火的案例。虽然,这种事情应该不会发生在你身上,但是数据竞争绝对是一个严重的错误,并且需要不惜一切代价避免它。
程序中的对同一内存地址中的数据访问存在竞争,你可以使用原子操作来避免未定义行为。当然,这不会影响竞争的产生——原子操作并没有指定访问顺序——但原子操作把程序拉回了定义行为的区域内。
修改顺序
程序中的对同一内存地址中的数据访问存在竞争,你可以使用原子操作来避免未定义行为。当然,这不会影响竞争的产生——原子操作并没有指定访问顺序——但原子操作把程序拉回了定义行为的区域内。如果对象不是一个原子类型,你必要确保有足够的同步操作,来确定每个线程都遵守了变量的修改顺序。当不同线程在不同序列中访问同一个值时,你可能就会遇到数据竞争或未定义行为。如果你使用原子操作,编译器就有责任去替你做必要的同步。