读后感介绍了volatile实现可见性的基本原理介绍了volatile不能实现原子性的示例,volatile复合操作不能实现原子性,读取值后在自增前改值可能被其它线程读取并修改,自增后刷新值可能会覆盖其它线程修改后的值介绍了实现原子性的三种方法及示例synchronized 修饰对象
ReentrantLock 使用lock()、unlock()加锁解锁,比synchronized功能更多,JDK6后性能和synchronized差不多
AtomicInteger 使用乐观锁
volatile关键字:
能够保证volatile变量的可见性不能保证volatile变量复合操作的原子性
volatile如何实现内存可见性:
深入来说:通过加入内存屏障和禁止重排序优化来实现的。
对volatile变量执行写操作时,会在写操作后加入一条store屏障指令对volatile变量执行读操作时,会在读操作前加入一条load屏障指令
通俗地讲:volatile变量在每次被线程访问时,都强迫从主内存中重读该变量的值,而当该变量发生变化时,又会强迫线程将最新的值刷新到主内存。这样任何时刻,不同的线程总能看到该变量的最新值。
线程写volatile变量的过程:
改变线程工作内存中volatile变量副本的值将改变后的副本的值从工作内存刷新到主内存
线程读volatile变量的过程:
从主内存中读取volatile变量的最新值到线程的工作内存中从工作内存中读取volatile变量的副本
volatile不能保证volatile变量复合操作的原子性:
Java代码privateintnumber=0;number++;//不是原子操作
它分为三步:
读取number的值
将number的值加1
写入最新的number的值
保证number自增操作的原子性:
使用synchronized关键字使用ReentrantLock使用AtomicInteger
使用synchronized关键字
Java代码importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;/***@authorInJavaWeTrust*/publicclassTestSynimplementsRunnable{privateintnumber=0;publicintgetNumber(){returnthis.number;}publicvoidrun(){increase();}publicvoidincrease(){synchronized(this){this.number++;}}publicstaticvoidmain(String[]args){ExecutorServiceexec=Executors.newFixedThreadPool(1000);TestSynsyn=newTestSyn();for(inti=0;i<1000;i++){exec.submit(syn);}System.out.println("number:"+syn.getNumber());exec.shutdown();}}
使用ReentrantLock
Java代码importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.locks.Lock;importjava.util.concurrent.locks.ReentrantLock;/***@authorInJavaWeTrust*/publicclassTestReeimplementsRunnable{privateLocklock=newReentrantLock();privateintnumber=0;publicintgetNumber(){returnthis.number;}publicvoidrun(){increase();}publicvoidincrease(){lock.lock();try{this.number++;}finally{lock.unlock();}}publicstaticvoidmain(String[]args){TestReeree=newTestRee();ExecutorServiceexec=Executors.newFixedThreadPool(1000);for(inti=0;i<1000;i++){exec.submit(ree);}System.out.println("number:"+ree.getNumber());exec.shutdown();}}
使用AtomicInteger
Java代码importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.atomic.AtomicInteger;/***@authorInJavaWeTrust*/publicclassTestAtomicimplementsRunnable{privatestaticAtomicIntegernumber=newAtomicInteger(0);publicvoidrun(){increase();}publicvoidincrease(){number.getAndAdd(1);}publicstaticvoidmain(String[]args){TestAtomicato=newTestAtomic();ExecutorServiceexec=Executors.newFixedThreadPool(1000);for(inti=0;i<1000;i++){exec.submit(ato);}System.out.println("number:"+number.get());exec.shutdown();}}
来自为知笔记(Wiz)