Java多线程学习--07

说明:参考《Java多线程核心技术》

13、volatile关键字

volatile关键字的作用:使变量在多个线程之间可见。
如果不是在在多继承的情况下,使用继承Thread和实现Runnable接口没有多大的区别。但是一旦出现多继承的情况,则用实现Runnable的方式处理多线程是个很有必要的。

public class PrintString implements Runnable{

    private boolean isContinue = true;

    public boolean isContinue() {
        return isContinue;
    }

    public void setContinue(boolean isContinue) {
        isContinue = isContinue;
    }

    public void printStringService() {
        try {
            while (isContinue == true) {
                System.out.println("ThreadName " + Thread.currentThread().getName());
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        printStringService();
    }
}
public class PrintStringTest {
    public static void main(String[] args) {
        PrintString printString = new PrintString();
        new Thread(printString).start();
        System.out.println("stop it... stopThreadName " + Thread.currentThread().getName());
        printString.setContinue(false);
    }
}
/**  dead loop
 stop it... stopThreadName main
 ThreadName Thread-0
 ThreadName Thread-0
 ThreadName Thread-0
 */


关键字volatile的作用是强制从公共堆栈中取得变量的值,而不是从线程私有数据栈中入得变量的值。

使用关键字volatile增加了实例变量在多个线程之间的可见性。

14、volatile和synchronized比较

关键字volatile和synchronized的比较:

1、关键字volatile是线程同步的轻量级的实现,所以volatile性能肯定比synchronized好,并且volatile只能修饰变量,而synchronized可以修饰方法和代码块、但是随着JDK版本的提升,synchronized关键字在效率上有了很大的提升。

2、多线程访问volatile不会发生阻塞,但是synchronized会发生阻塞。

3、volatile能保证共享变量之间的可见性,但是不能保证原子性;而synchronized能保证原子性,也可以间接保证共享变量的可见性格,因为它会将私有内存共有内存中的数据做同步。

4、volatile关键字解决的是变量在多个线程之间的可见性,而synchronized关键字解决的是多个线程之间访问资源的同步性。

15、volatile的非原子特性

关键字volatile虽然增减了实例变量在多个线程之间的可见性,但它却不具备同步性,那么就不具备原子性。

public class UnAtomicity extends Thread{

    volatile public static int count;

    private static void addCount(){
        for (int i = 0; i < 100; i++) {
            count++;
        }
        System.out.println("count = " + count);
    }

    @Override
    public void run(){
        addCount();
    }
}
public class UnAtomicityTest {

    public static void main(String[] args) {
        UnAtomicity[] unAtomicities = new UnAtomicity[100];
        for (int i = 0; i < 100 ; i++) {
            unAtomicities[i] = new UnAtomicity();
            unAtomicities[i].start();
        }
    }
}
/**
 count = 9686
 count = 9886
 count = 9886
 count = 9786
 count = 9786
 count = 9786
 count = 9786
 */

关键字volatile提示线程每次从共享内存中读取变量,而不是从内存中读取,这样就保证了同步数据的可见性。

表达式i++:并不是一个操作,而是三个,因此才会造成上述的现象:

1、从内存中读取i的值

2、计算i的值

3、将i的值写入内存中。

如果将 volatile public static int count;改为 synchronized public static int count; 就不会发生上述的线程。注意必须加static关键字,这样才能锁住Class类了。

总结

关键字volatile对于修饰的变量,JVM虚拟机只是保证从主存中加载到线程工作内存的值是最新的。其解决的是变量在读操作时的可见性问题,但无法保证原子性,对于多个线程访问同一变量还是需要加锁同步的。

关键字synchronized可以保证同一时刻,只有一个线程可以执行某一方法或者某一个代码块,其包含了两个特征:互斥性和可见性。同步synchronized不仅可以解决一个线程看到对象处于不一致的状态,还可以保证进入同步方法或者同步代码块的每个线程,都可到由同一个锁保护之前的所有修改结果。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值