厦门h5网站建设,中企动力科技股份官网,北京朝阳区属于几环,南海建设工程交易中心网站1.volatile关键字
1作用#xff1a;强制线程每次在使用的时候,都会看一下共享区域最新的值[用于提供线程安全] 2与synchronized的区别和联系#xff1a; 把代码块声明为 synchronized#xff0c;有两个重要后果#xff0c;通常是指该代码具有 原子性1作用强制线程每次在使用的时候,都会看一下共享区域最新的值[用于提供线程安全] 2与synchronized的区别和联系 把代码块声明为 synchronized有两个重要后果通常是指该代码具有 原子性atomicity和 可见性visibility) volatile变量具有 synchronized 的可见性特性但是不具备原子性。这就是说线程能够自动发现 volatile 变量的最新值 3使用条件 您只能在有限的一些情形下使用 volatile 变量替代锁。要使 volatile 变量提供理想的线程安全必须同时满足下面两个条件 a.对变量的写操作不依赖于当前值。 b.该变量没有包含在具有其他变量的不变式中 注【单独使用 volatile 还不足以实现计数器、互斥锁或任何具有与多个变量相关的不变式的类例如 “start end”】
4实现场景【结婚基金问题】
//volatile关键字:强制线程每次在使用的时候,都会看一下共享区域最新的值
public class Demo1 {public static void main(String[] args) {//结婚基金问题Girl girl new Girl();Boy boy new Boy();girl.start();boy.start();}
}//Boy类
public class Boy extends Thread {Overridepublic void run() {try {Thread.sleep(10);Money.money 90000;} catch (InterruptedException e) {e.printStackTrace();}}
}//Girl类
public class Girl extends Thread{Overridepublic void run() {while (true){while (Money.money100000){}System.out.println(基金不是十万了);break;}}
}//Money
public class Money {//1.volatile关键字:强制线程每次在使用的时候,都会看一下共享区域最新的值public static volatile int money100000;//2.同步代码块/*public static int money100000;public static final Object lock new Object();*/
}打印结果
--------------------------------------------------------------------------------
基金不是十万了2.AtomicInteger[原子类]的原子性
1概念 原子性指意思是多个操作是不可分割的原子项他们要么同时成功要么同时失败 2原理 主内存【堆】线程本地内存【栈】 自增操作count为例其实底层是要完成三个步骤(这三个步骤是不可分割的) 1.从主内存拷贝一个变量副本到线程本地内存 2.对变量副本进行操作 3.把变量副本的值写回主内存 但是由于CPU的随机性可能一个线程没有完成这个三个步骤执行权被其他线程抢走了就破坏了原子性。
3AtomicInteger[原子类] 方法
//AtomicInteger[原子类] 方法
public class Demo2 {public static void main(String[] args) {//构造方法1 public AtomicInteger() 空参构造,初始值默认为0//构造方法2 public AtomicInteger(int number) 初始值默认为int//int get():获取值AtomicInteger ac new AtomicInteger(10);System.out.println(ac.get());//get返回的值可再进行其他操作//int getAndIncrement():以原子方式将当前值加1注意这里返回的是自增前的值。System.out.println(ac.getAndIncrement());System.out.println(ac);System.out.println(----------------------------------------);//int incrementAndGet():以原子方式将当前值加1注意这里返回的是自增后的值。AtomicInteger ac2 new AtomicInteger(10);System.out.println(ac2.incrementAndGet());//int addAndGet(int data):以原子方式将参数与对象中的值相加并返回结果。System.out.println(ac2.addAndGet(10));//int getAndSet(int value):以原子方式设置为newValue的值并返回旧值。System.out.println(ac2.getAndSet(30));//查看新值System.out.println(ac2);}
}打印结果
--------------------------------------------------------------------------------
10
10
11
----------------------------------------
11
21
21
304AtomicInteger保证线程安全【小男孩送冰淇淋案例】
public class Demo1 {public static void main(String[] args) {MyAtomThread myAtomThread new MyAtomThread();for (int i 0; i 100; i) {new Thread(myAtomThread).start();}}
}//具体实现类
public class MyAtomThread implements Runnable {private int count 0;//记录送冰淇淋的数量Overridepublic void run() {for (int i 0; i 100; i) {//1,从共享数据中读取数据到本线程栈中//2,修改本线程栈中变量副本的值//3,会把本线程栈中变量副本的值赋值给共享数据count;System.out.println(已经送了count冰淇淋);}}
}打印结果
--------------------------------------------------------------------------------
已经送了1冰淇淋
......
已经送了9999冰淇淋
已经送了10000冰淇淋5AtomicInteger原子性原理 :CAS算法和自旋
先获取主内存变量值 // 在修改共享数据的时候把原来的旧值记录下来了。 // 如果现在内存中的值跟原来的旧值一样[compareAndSet]证明没有其他线程操作过内存值则修改成功。 compareAndSet【比较内存中的值旧值是否相等如果相等就把修改后的值写到内存中返回true,表示修改成功】 // 如果现在内存中的值跟原来的旧值不一样了[compareAndSet]证明已经有其他线程操作过内存值了。 // 则修改失败需要获取现在最新的值再次进行操作这个重新获取就是自旋。
3.悲观锁【synchronized】和乐观锁【CAS】
1相同点:在多线程情况下都可以保证共亨数据的安全性。
2不同点: synchronized总是从最坏的角度出发认为每次获取数据的时候别人都有可能修改。所以在每次操作共享数据之前都会上锁。悲观锁) cas是从乐观的角度出发假设每次获取数据别人都不会修改所以不会上锁。只不过在修改共享数据的时候会检查一下别人有没有修改过这个数据。 如果别人修改过那么我再次获取现在最新的值。 如果别人没有修改过那么我现在直接修改共享数据的值。(乐观锁)
【注synchronized和volatile都不具备原子性】