java 多线程 volatile 关键字

来源:互联网 发布:视频机器码破解软件 编辑:程序博客网 时间:2024/05/01 01:42

volatile概念:主要作用是使变量在多个线程间可见



public class RunThread extends Thread{private volatile boolean isRunning = true;private void setRunning(boolean isRunning){this.isRunning = isRunning;}public void run(){System.out.println("进入run方法..");int i = 0;while(isRunning == true){//..}System.out.println("线程停止");}public static void main(String[] args) throws InterruptedException {RunThread rt = new RunThread();rt.start();Thread.sleep(1000);rt.setRunning(false);System.out.println("isRunning的值已经被设置了false");}}

输出结果:

进入run方法..
线程停止
isRunning的值已经被设置了false


示例总结:

在Java中,每一个线程都会有一块哦工作内存区,其中存放着所有线程共享的主内存肿的变量值的拷贝,当线程执行时,他在自己的工作内存肿操作这些变量,为了存取一个共享的变量,一个线程通常先获取锁定并去清除它的内存工作区,把这些共享变量从所有线程的共享内存区中正确的装入到她自己的工作内存肿,当线程解锁时保证该工作内存区中的变量的值写回到共享内存中

volatile的作用就是强制线程到主内存中去读取变量,而不去线程工作内存区里去读取,从而实现了多个线程间的变量可见,也就是满足线程安全的可见性,但不具备原子性(同步性)。一般volatile只针对与多个线程可见的变量操作,并不能代理synchronized的同步功能。




package com.bjsxt.base.sync007;import java.util.concurrent.atomic.AtomicInteger;/** * volatile关键字不具备synchronized关键字的原子性(同步) * @author alienware * */public class VolatileNoAtomic extends Thread{private static volatile int count;//private static AtomicInteger count = new AtomicInteger(0);private static void addCount(){for (int i = 0; i < 1000; i++) {count++ ;//count.incrementAndGet();}System.out.println(count);}public void run(){addCount();}public static void main(String[] args) {VolatileNoAtomic[] arr = new VolatileNoAtomic[100];for (int i = 0; i < 10; i++) {arr[i] = new VolatileNoAtomic();}for (int i = 0; i < 10; i++) {arr[i].start();}}}
输出结果:

2000
3000
3994
3218
5792
2000
4792
6792
7792
8792

package com.bjsxt.base.sync007;import java.util.concurrent.atomic.AtomicInteger;/** * volatile关键字不具备synchronized关键字的原子性(同步) * @author alienware * */public class VolatileNoAtomic extends Thread{//private static volatile int count;private static AtomicInteger count = new AtomicInteger(0);private static void addCount(){for (int i = 0; i < 1000; i++) {//count++ ;count.incrementAndGet();}System.out.println(count);}public void run(){addCount();}public static void main(String[] args) {VolatileNoAtomic[] arr = new VolatileNoAtomic[100];for (int i = 0; i < 10; i++) {arr[i] = new VolatileNoAtomic();}for (int i = 0; i < 10; i++) {arr[i].start();}}}

输出结果:

3395
5000
6000
4000
3395
3395
7000
9728
10000
10000

示例总结:

volatile只具备可见性,没有原子性,要实现原子性建议使用atomic类的系列对象,支持原子性操作



原子性:
原子是世界上的最小单位,具有不可分割性。比如 a=0;(a非long和double类型) 这个操作是不可分割的,那么我们说这个操作时原子操作。再比如:a++; 这个操作实际是a = a + 1;是可分割的,所以他不是一个原子操作。非原子操作都会存在线程安全问题,需要我们使用同步技术(sychronized)来让它变成一个原子操作。一个操作是原子操作,那么我们称它具有原子性。Java的concurrent包下提供了一些原子类,我们可以通过阅读API来了解这些原子类的用法。比如:AtomicInteger、AtomicLong、AtomicReference等。
可见性:
可见性,是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的。也就是一个线程修改的结果。另一个线程马上就能看到。比如:用volatile修饰的变量,就会具有可见性。volatile修饰的变量不允许线程内部缓存和重排序,即直接修改内存。所以对其他线程是可见的。但是这里需要注意一个问题,volatile只能让被他修饰内容具有可见性,但不能保证它具有原子性。比如 volatile int a = 0;之后有一个操作 a++;这个变量a具有可见性,但是a++ 依然是一个非原子操作,也就这这个操作同样存在线程安全问题。

0 0
原创粉丝点击