当前位置: 首页 > 后端技术 > Java

师兄:i++是线程安全的吗?

时间:2023-04-01 23:59:56 Java

送你以下java学习资料。文末有收藏方法。volatile关键字保证了在多线程环境下,修改后的变量会在修改后立即同步到主存中,这样线程对变量的修改是对所有其他线程可见的,其他线程可以立即读取修改后的值。Thread的本地内存每个Thread都有自己的线程存储空间。Thread何时将本地存储空间中的数据同步到主存中是不确定的。例子借用了GoogleJEREMYMANSON的解释,上图表示两个线程并发执行,代码顺序为Thread1->Thread21,不带volatile如果ready字段不使用volatile,那么Thread1对ready做的修改可能对Thread2不可见,是否可见不确定。如果此时thread1ready被泄露(leakthrough),那么Thread2可以看到ready为true,但是有可能answer的变化没有被泄露,那么thread2可能会输出0(answer=42是不可见的)thread2)2.使用volatile之后,使用volatile之后,做了下面的事情。volatile变量每修改一次,都会同步到主存。每次读取volatile变量的值时,都会强制从主存中读取最新的值(强制)JVM无法优化volatile变量,比如JVM优化后,读取的变量会改用cpucache从主内存读取。)线程A在volatile变量之前写入变量visible。在线程B中读取volatile变量后,线程B对于A中的其他可见变量也是可见的。换句话说,写入volatile类似于退出一个synchronized块,读取volatile类似于进入一个synchronized块。所以如果使用volatile,Thread2读取的值是read=>true,answer=>42,当然使用volatile也会增加性能开销。注意volatile不保证解决非source操作的多线程安全问题。volatile解决了多线程之间共享变量的可见性问题,比如多线程的i++,++i还有多线程的问题,解决不了。如下:使用一个线程i++,另一个i--,最终结果不为0publicclassVolatileTest{privatestaticvolatileintcount=0;privatestaticfinalinttimes=Integer.MAX_VALUE;publicstaticvoidmain(String[]args){longcurTime=System.nanoTime();线程decThread=startdec.Thread(read);;//使用run()运行的结果为0,因为单线程执行不会有线程安全问题//newDecThread().run();System.out.println("启动线程:"+Thread.currentThread()+"i++");for(inti=0;i值+1->将+1后的值写回i,这样在多线程中的执行类似于下面Thread1Thread2r1=i;r3=i;r2=r1+1;r4=r3+1;i=r2;i=r4;这样会造成的问题是r1和r3读到的值都是0,最后两个线程向i写1,最后i等于1,但是进行了两次自增操作,可见加volatile或者不加volatile都不能解决non的线程同步问题-原子操作。线程同步问题的解决Java提供了java.util.concurrent.atomic包来提供threadsSafe基本类型包装类,示例如下micInteger;/***@authorzhenwei.liu创建于201313-9-2pm10:18*@version$Id$*/publicclassSafeTest{privatestaticAtomicIntegercount=newAtomicInteger(0);privatestaticfinalinttimes=Integer.MAX_VALUE;publicstaticvoidmain(String[]args){longcurTime=System.nanoTime();线程decThread=newDecThread();decThread.start();0,原因是单线程执行不会有线程安全问题//newDecThread().run();System.out.println("启动线程:"+Thread.currentThread()+"i++");for(inti=0;i