python local关键词具体用法 Java如何解决可见性和有序性的问题?
Java如何解决可见性和有序性的问题?
线程安全有三个特征:原子性、可见性和有序性,只有满足这三个特征,线程安全才能得到保证。这三个特征详细描述如下:
1.原子性:通常指代码执行的效果,要么全部成功,要么全部失败;
2.可见性:一个线程的本地内存中的变量值应该立即同步到主存中,以便其他线程看到;
3.有序性:保证代码执行的序列化;
java中的原子性操作主要是通过使用sun.misc.Unsafe包下的compareAndSwap方法来实现的,这是sun包下的一个原生方法,通过使用C代码在CPU级别保证底层指令的原子性来实现,或者通过加锁来实现!
但是,CAS会有问题。详见我另一个回答,不赘述!
能见度可以 t得不到保证主要是因为内存和CPU的访问速度有差距,所以在CPU和主存之间引入了cache(线程本地内存)的概念来提高CPU的计算性能。副作用是当线程共享数据时,中间数据可能 不能保证是最新的(可能在其他线程的本地内存中汇总)!
因为编译器和处理器将基于性能考虑重新排序操作指令,所以不能保证有序性。单线程没有问题,但是多线程的话可能会有误判!
编译器的重新排序也是有规律的。java与生俱来的有序性构成了先发生后处理原则。如果发生在之前原则不能推导出指令的执行顺序,那么指令就是不有序的。happens-before的八个原则是:程序顺序规则(单线程中的顺序不能由多线程保证)和加锁规则(同一个锁先解锁,再加锁)。Volatile变量规则(先写后读)、转移规则(类似于A在B之前,B在C之前,A在C之前)、线程启动原则(start方法是线程执行的第一个方法)、线程中断规则、线程终止规则、对象终止规则!发生之前的八个原则规定了指令执行的顺序。
可见,线程不安全的原因十有是对性能的追求!
通常代码满足这三个特征就能保证线程安全。java中保证线程安全的方法有很多,包括加锁和解锁。让 让我们一个一个地谈论它们:
1.锁定:比如synchronized(JDK自带的关键字,JMM规定在获取锁时,必须清除工作内存中的变量值,以保证变量只能在需要的时候从主存中获取;在释放锁的时候,一定要把最新的值写入主存,这样才能保证数据的可见性和原子性!
根据AQS改编的《重入者》。Ck、ReentrantReadWriteLock等。全都锁上了!
2、无锁:
①使用volatile CAS操作,volatile利用内存屏障保证变量的可见性和指令的顺序,CAS保证原子性,最终实现线程安全。在jdk中,以atomic开头的几个类都是用这个方法实现线程安全的!如下图所示:
2.使用ThreadLocal,每个线程在其本地内存中维护一份数据的副本,相当于没有共享资源的竞争,所以不会有线程安全问题;
还会有更多的JAVA开发技术或者面试问题持续分享,希望能帮助到更多的朋友,敬请关注。。
VFP里面的问题?
变量的范围分为全局、局部和局部,分别由关键字public、private和local定义。
1.全局变量是指在所有程序模块中都有效的内存变量。程序或进程结束后,全局变量不会自动释放。如果清除,必须使用释放命令。
2.局部变量指的是在建立它们的程序模块和被这个程序模块调用的程序模块中有效的内存变量。一旦局部变量离开了定义它们的程序,它们就失去了意义。在程序中没有被描述为全局的内存变量被认为是局部变量。局部变量也可以用PRIVATE来描述。
3.由Local定义的局部内存变量只能存在于定义它的程序中。一旦定义它的程序运行,局部变量将从内存中释放。
版权声明:本文内容由互联网用户自发贡献,本站不承担相关法律责任.如有侵权/违法内容,本站将立刻删除。