简介:
SMP 的全称是“Symmetric Multi-Processor”(对称多处理器)。这种设计的特点是两个或多个相同的 CPU 核心共同访问主内存。几年前,所有 Android 设备都还是采用单处理器 (UP)。
大多数(即便不是所有)Android 设备总是有多个 CPU,但是过去只会有一个 CPU 用于运行应用,其他 CPU 则用于管理各种设备硬件(例如无线装置)。CPU 可能具有不同的架构,在其上运行的程序无法使用主内存相互通信。
目前市面上的大多数 Android 设备都是采用 SMP 设计构建的,这使得软件开发者的工作变得有些复杂。多线程程序中的竞态条件可能不会在单处理器上引发明显问题,但如果两个或多个线程同时在不同核心上运行,就可能会经常出现故障。
技术点
1. 在SMP架构下,至少两个线程同时访问相同的普通数据,并且其中至少一个线程对其进行修改时,就会发生数据争用。另外<普通数据>指的是并非专用于线程通信的同步对象的数据。互斥量/条件变量/java-volatile/C++原子对象都不是普通数据,对他们访问允许竞争。
2. 在SMP架构下,至少两个线程同时访问相同的接口(interface),并且其中至少一个线程对其进行修改时,就会发生数据争用。
实现方案
1. 避免数据争用
现代编程语言提供了很多同步机制以避免出现数据争用;最基本的工具包括:
1.1 锁/互斥量
1). 互斥锁
Linux C中:mutex_lock
2). 线程互斥锁
C++11 : std::mutex 或 pthread_mutex_t
顾名思义:线程互斥锁,
3). java synchronized同步锁
synchroancized是vJava中的关键字,是一种同步锁。它修饰的对象有以下几种:
a. 修饰b一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
b. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
c. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
d. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。
总结:如上可用于确保某些代码段不会与访问相同数据的其他代码段同时运行。我们将这些工具及其他类似工具统称为“锁”。在访问共享数据结构之前始终获取特定锁并在之后将其释放,可防止在访问数据结构时出现数据争用。
1.2 volatile/atomic变量
Java 提供 volatile 字段,这些字段支持并发访问,而不会引入数据争用。自 2011 年以来,C 和 C++ 就支持具有类似语义的 atomic 变量和字段。这些变量和字段通常比锁更难使用,因为它们只确保对单个变量的单独访问是原子性的(在 C++ 中,这通常会扩展到简单的读取-修改-写入操作,例如增量操作。Java 需要特殊的方法调用才能实现此类操作)。与锁不同的是,volatile 或 atomic 变量不能直接用于阻止其他线程干扰较长的代码序列。
请务必注意,volatile 在 C++ 和 Java 中的意义大不相同。在 C++ 中,volatile 不会阻止数据争用,但由于缺少 atomic 对象,较旧的代码通常会将其用作解决方法。如今已不再建议这样做,在 C++ 中,对于可供多个线程并发访问的变量,请使用 atomic<T>。C++ volatile 旨在用于设备寄存器等。
2. 使用案例
2.1 互斥锁:
1). Linux C中:
/*
*#include<linux/mutex.h>
*void mutex_init(struct mutex *lock);
*void mutex_lock(struct mutex *lock);
*void mutex_unlock(struct mutex *lock);
*/
struct mutex_lock m_lock;
mutex_init(&m_lock);//初始化
mutex_lock(&m_lock);//上锁
//do something
mutex_unlock(&m_lock);//释放锁
2). C++ 中:
/*
*#include <pthread.h>
*//PTHREAD_MUTEX_INITIALIZERatt
*int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);//初始化锁变量mutex, attr为锁属性,NULL值为默认属性。
*int pthread_mutex_destroy(pthread_mutex_t *mutex);
*int pthread_mutex_tlock(pthread_mutex_t *mutex);
*int pthread_mutex_trylock(pthread_mutex_t *mutex);
*int pthread_mutex_unlock(pthreadd_mutex_t *mutex);
*/
eg:
pthread_mutex_t mutex_lock;
pthread_mutex_init(&mutex_lock, NULL);//初始化
或者:
pthread_mutex_t mutex_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&mutex_lock);//上锁
//do something
pthread_mutex_unlock(&mutex_lock);//释放锁
pthread_mutex_destroy(&mutex_lock);//销毁锁
3).java: