在上一节中主要讲了JVM内存模型和线程安全的可见性问题,本节重点讲解线程安全的原子操作;
竞态条件与临界区
代码示例
public class IncrDemo {
public int i = 0;
public void incr() {
i++; //临界区
}
}
共享资源
不可变对象
原子操作定义
CAS机制
J.U.C包内的原子操作封装类
线程安全代码示例
volatile线程安全示例:
public class LockDemo1 {
volatile int value = 0;
// 直接操作内存,修改对象,数组内存....强大的API
static Unsafe unsafe;
private static long valueOffset;
static {
try {
// 反射技术获取unsafe值
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = (Unsafe) field.get(null);
// 获取到 value 属性偏移量(用于定于value属性在内存中的具体地址)
valueOffset = unsafe.objectFieldOffset(LockDemo1.class.getDeclaredField("value"));
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void add() {
// TODO xx00
// i++;// JAVA 层面三个步骤
// CAS + 循环 重试
int current;
do {
// 操作耗时的话, 那么 线程就会占用大量的CPU执行时间
current = unsafe.getIntVolatile(this, valueOffset);
} while (!unsafe.compareAndSwapInt(this, valueOffset, current, current + 1));
// 可能会失败
}
public static void main(String[] args) throws InterruptedException {
LockDemo1 ld = new LockDemo1();
for (int i = 0; i < 2; i++) {
new Thread(() -> {
for (int j = 0; j < 10000; j++) {
ld.add();
}
}).start();
}
Thread.sleep(2000L);
System.out.println(ld.value);
}
}
synchronized线程安全示例:
public class LockDemo2 {
int i = 0;
public void add() {
synchronized (this) {
i++;
}
}
public static void main(String[] args) throws InterruptedException {
LockDemo2 ld = new LockDemo2();
for (int i = 0; i < 2; i++) {
new Thread(() -> {
for (int j = 0; j < 10000; j++) {
ld.add();
}
}).start();
}
Thread.sleep(2000L);
System.out.println(ld.i);
}
}
Lock线程安全示例:
public class LockDemo3 {
volatile int i = 0;
Lock lock = new ReentrantLock();
public void add() {
lock.lock();
try {
i++;
}finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
LockDemo3 ld = new LockDemo3();
for (int i = 0; i < 20; i++) {
new Thread(() -> {
for (int j = 0; j < 10000; j++) {
ld.add();
}
}).start();
}
Thread.sleep(2000L);
System.out.println(ld.i);
}
}
atomic线程安全示例:
public class LockDemo4 {
// volatile int i = 0;
AtomicInteger i = new AtomicInteger(0);
public void add() {
// TODO xx00
// i++;// 三个步骤
i.incrementAndGet();
}
public static void main(String[] args) throws InterruptedException {
LockDemo4 ld = new LockDemo4();
for (int i = 0; i < 2; i++) {
new Thread(() -> {
for (int j = 0; j < 10000; j++) {
ld.add();
}
}).start();
}
Thread.sleep(2000L);
System.out.println(ld.i);
}
}
线程安全操作效率对比
// 测试用例: 同时运行2秒,检查谁的次数最多
public class LongAdderDemo {
private long count = 0;
// 同步代码块的方式
public void testSync() throws InterruptedException {
for (int i = 0; i < 3; i++) {
new Thread(() -> {
long starttime = System.currentTimeMillis();
while (System.currentTimeMillis() - starttime < 2000) { // 运行两秒
synchronized (this) {
++count;
}
}
long endtime = System.currentTimeMillis();
System.out.println("SyncThread spend:" + (endtime - starttime) + "ms" + " v" + count);
}).start();
}
}
// Atomic方式
private AtomicLong acount = new AtomicLong(0L);
public void testAtomic() throws InterruptedException {
for (int i = 0; i < 3; i++) {
new Thread(() -> {
long starttime = System.currentTimeMillis();
while (System.currentTimeMillis() - starttime < 2000) { // 运行两秒
acount.incrementAndGet(); // acount++;
}
long endtime = System.currentTimeMillis();
System.out.println("AtomicThread spend:" + (endtime - starttime) + "ms" + " v-" + acount.incrementAndGet());
}).start();
}
}
// LongAdder 方式
private LongAdder lacount = new LongAdder();
public void testLongAdder() throws InterruptedException {
for (int i = 0; i < 3; i++) {
new Thread(() -> {
long starttime = System.currentTimeMillis();
while (System.currentTimeMillis() - starttime < 2000) { // 运行两秒
lacount.increment();
}
long endtime = System.currentTimeMillis();
System.out.println("LongAdderThread spend:" + (endtime - starttime) + "ms" + " v-" + lacount.sum());
}).start();
}
}
public static void main(String[] args) throws InterruptedException {
LongAdderDemo demo = new LongAdderDemo();
demo.testSync();
demo.testAtomic();
demo.testLongAdder();
}
}
控制台输出(随机):
SyncThread spend:2000ms v24158152
SyncThread spend:2000ms v24158151
SyncThread spend:2000ms v24184392
AtomicThread spend:2000ms v-112956795
AtomicThread spend:2000ms v-112956796
AtomicThread spend:2000ms v-112956797
LongAdderThread spend:2000ms v-151089455
LongAdderThread spend:2000ms v-151089455
LongAdderThread spend:2000ms v-151089455
来源:CSDN
作者:大马士革刀
链接:https://blog.csdn.net/maxleader/article/details/104172894