保证可见性
package icu.lookyousmileface.volatilecode;
import java.util.concurrent.Executors;
import java.util.concurrent.linkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class VolatileShow {
private volatile static int num = 0;
public static void main(String[] args) {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
5,
Runtime.getRuntime().availableProcessors(),
5,
TimeUnit.SECONDS,
new linkedBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardOldestPolicy()
);
//线程1对内存中num=1的变化不知道
threadPoolExecutor.execute(() -> {
while (num == 0) {
}
});
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
num = 1;
System.out.println("num:"+num);
threadPoolExecutor.shutdown();
}
}
不保证原子性
原子性 : 不可分割
线程A在执行任务的时候,不能被打扰的,也不能被分割。要么同时成功,要么同时失败。
public class VolatileNotAtomic {
private volatile static int num = 0;
public static void add(){
num++;
}
public static void main(String[] args) {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
5,
Runtime.getRuntime().availableProcessors(),
5,
TimeUnit.SECONDS,
new linkedBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy()
);
try {
for (int i = 1; i <= 20; i++) {
threadPoolExecutor.execute(() -> {
for (int j = 1; j <= 1000; j++) {
add();
}
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPoolExecutor.shutdown();
}
Thread.currentThread().getThreadGroup().list();
System.out.println("sum:" + num);
}
}
为了保证原子性,不实用sync、lock,可以使用atomic包下的原子类
public class AtomicUse {
private volatile static AtomicInteger number = new AtomicInteger();
public static void add(){
number.getAndIncrement();
}
public static void main(String[] args) {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
5,
Runtime.getRuntime().availableProcessors(),
5,
TimeUnit.SECONDS,
new linkedBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy()
);
try {
for (int i = 1; i <= 20; i++) {
threadPoolExecutor.execute(()->{
for (int j = 1; j <= 1000; j++) {
add();
}
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPoolExecutor.shutdown();
}
while (Thread.activeCount()>2){
System.out.println(Thread.currentThread().getName());
Thread.yield();
}
System.out.println("result:"+number);
}
}
禁止指令重排
什么是 指令重排:你写的程序,计算机并不是按照你写的那样去执行的。
源代码–>编译器优化的重排–> 指令并行也可能会重排–> 内存系统也会重排—> 执行
处理器在进行指令重排的时候,考虑:数据之间的依赖性!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oVkWRf6K-1644224594265)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/acc5d510-aa44-4c78-bcba-854975117af7/Untitled.png)]
单例模式
饿汉 单例模式
public class Hungry {
private Hungry(){
}
private final static Hungry HUNGRY = new Hungry();
public static Hungry getInstance(){
return HUNGRY;
}
}
懒汉 单例模式
public class LazyMan {
private volatile static LazyMan lazyMan;
private static boolean lockSkey = false;
private LazyMan() {
synchronized (LazyMan.class){
if (lockSkey == false){
lockSkey = true;
}else {
throw new RuntimeException("不要妄图使用反射破坏!");
}
}
}
// 双重检测锁模式的 懒汉式单例 DCL懒汉式
public static LazyMan getInstance() {
if (lazyMan == null) {
synchronized (LazyMan.class){
if (lazyMan==null){
lazyMan = new LazyMan();
}
}
}
return lazyMan;
}
}
静态内部类
public class StaticClass {
private StaticClass(){
}
private static class InnerClass{
private static final Holder HOLDER = new Holder();
}
private static Holder getInstenac(){
return InnerClass.HOLDER;
}
}
CAS
修内功,操作系统,计算机网络原理。
原子类
public class CasUse {
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(12);
//期望值,更新值
System.out.println(atomicInteger.compareAndSet(12, 66));
System.out.println(atomicInteger.get());
System.out.println(atomicInteger.compareAndSet(66, 99));
System.out.println(atomicInteger.get());
}
}
Unsafe类
import java.util.function.IntUnaryOperator;
import java.util.function.IntBinaryOperator;
import sun.misc.Unsafe;
public class AtomicInteger extends Number implements java.io.Serializable {
private static final long serialVersionUID = 6214790243416807050L;
// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
⚠️ Java无法操作内存,c++可以,Java操作C++,C++再操作内存
public final int getAndAddInt(Object o, long offset, int delta) {
int v;
do {
//内存中的值
v = getIntVolatile(o, offset);
//自旋锁,CAS : 比较当前工作内存中的值和主内存中的值,如果这个值是期望的,那么则执行操作!如果不是就一直循环!
} while (!compareAndSwapInt(o, offset, v, v + delta));
return v;
}
缺点:
1、 循环会耗时
2、一次性只能保证一个共享变量的原子性
3、ABA问题
ABA问题(立马换太子)
public class CasABAProblem {
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(20);
//====================捣乱换太子=============
atomicInteger.compareAndSet(20,66);
atomicInteger.compareAndSet(66,20);
//==================== 不知情的线程===========
atomicInteger.compareAndSet(20,99);
System.out.println(atomicInteger.get());
}
}
原子引用
解决ABA 问题,引入原子引用! 对应的思想:乐观锁!
带版本号 的原子操作!
试验代码
package icu.lookyousmileface.cas;
import java.util.concurrent.Executors;
import java.util.concurrent.linkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicStampedReference;
public class ReferenceUse {
public static void main(String[] args) {
AtomicStampedReference atomicRefe = new AtomicStampedReference<>(1, 1);
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
5,
Runtime.getRuntime().availableProcessors(),
5,
TimeUnit.SECONDS,
new linkedBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy()
);
try {
threadPoolExecutor.execute(()->{
int stamp = atomicRefe.getStamp();
System.out.println(Thread.currentThread().getName()+"=>"+stamp);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
atomicRefe.compareAndSet(1,2,atomicRefe.getStamp(),atomicRefe.getStamp()+1);
System.out.println(Thread.currentThread().getName()+"=>"+atomicRefe.getStamp());
System.out.println(atomicRefe.compareAndSet(2, 1, atomicRefe.getStamp(), atomicRefe.getStamp() + 1));
System.out.println(Thread.currentThread().getName()+"=>"+atomicRefe.getStamp());
});
threadPoolExecutor.execute(()->{
int stamp = atomicRefe.getStamp();
System.out.println(Thread.currentThread().getName()+"=>"+stamp);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(atomicRefe.compareAndSet(1, 2, stamp, stamp + 1));
System.out.println(Thread.currentThread().getName()+"=>"+atomicRefe.getStamp());
});
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPoolExecutor.shutdown();
}
}
}
⚠️ Tips:Integer 使用了对象缓存机制,默认范围是 -128 ~ 127 ,推荐使用静态工厂方法 valueOf 获取对象实例,而不是 new,因为 valueOf 使用缓存,而 new 一定会创建新的对象分配新的内存空间;



