java volatile的原理_Java的并发编程:深入理解volatile的原理和使用 - Break易站

我们已经知道,synchronized关键字可以保证线程的安全,但是相对来说,synchronized关键字还是比较重量级的锁。虽然,JDK6之后引入了偏向锁,轻量级锁和重量级锁,但是还是比较重量的。而volatile关键字的引入就是为了轻量化。

Java中volatile的原理

volatile主要有下面几个特征:

Volatile称之为轻量级锁,被volatile修饰的变量,在线程之间是可见的。

可见性:一个线程修改了这个变量的值,在另外一个线程中能够读到这个修改后的值。

Synchronized除了线程之间互斥意外,还有一个非常大的作用,就是保证可见性

但是呢,Synchronized可以实现的,volatile并不一定能实现,对于非原子性的操作,volatile并不一定能实现。

Java中volatile的使用和实例解析

我们要保证数据的可见性,就是希望能在set方法之后,才那个这个数字的值,而不是拿到原来的值,下面的程序加上synchronized关键字可以实现(可以试试去掉,synchronized关键字,看看输出的结果):

package com.breakyizhan.thread.t7;

/**

* 保证可见性的前提

*

* 多个线程拿到的是同一把锁,否则是保证不了的。

*

* @author worker

*

*/

public class Demo {

public int a = 1;

public synchronized int getA() {

return a;

}

public synchronized void setA(int a) {

try {

Thread.sleep(2);

} catch (InterruptedException e) {

e.printStackTrace();

}

this.a = a;

}

public static void main(String[] args) {

Demo demo = new Demo();

new Thread(new Runnable() {

@Override

public void run() {

demo.setA(10);

}

}).start();

new Thread(new Runnable() {

@Override

public void run() {

System.out.println(demo.getA());

}

}).start();

try {

Thread.sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("最终的结果为:" + demo.getA());

}

}

输出:

10

最终的结果为:10

那么我们知道要保证int a的可见性,还可以在前面加上关键字volatile,具体的代码如下:

package com.breakyizhan.thread.t7;

/**

* 保证可见性的前提

*

* 多个线程拿到的是同一把锁,否则是保证不了的。

*

* @author worker

*

*/

public class Demo {

public volatile int a = 1;

public int getA() {

return a;

}

public void setA(int a) {

try {

Thread.sleep(2);

} catch (InterruptedException e) {

e.printStackTrace();

}

this.a = a;

}

public static void main(String[] args) {

Demo demo = new Demo();

demo.a = 10;

new Thread(new Runnable() {

@Override

public void run() {

System.out.println(demo.a);

}

}).start();

try {

Thread.sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("最终的结果为:" + demo.getA());

}

}

输出:

10

最终的结果为:10

Java中volatile的实用例子

在第一个程序执行了第10次之后,第二个程序才执行,那么,我们要实现的代码如下:

package com.breakyizhan.thread.t7;

public class Demo2 {

public volatile boolean run = false;

public static void main(String[] args) {

Demo2 d = new Demo2();

new Thread(new Runnable() {

@Override

public void run() {

for(int i = 1;i<=10;i++) {

System.err.println("执行了第 " + i + " 次");

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

d.run = true;

}

}).start();

new Thread(new Runnable() {

@Override

public void run() {

while(!d.run) {

// 不执行

//自旋

}

System.err.println("线程2执行了...");

}

}).start();

}

}

输出:

执行了第 1 次

执行了第 2 次

执行了第 3 次

执行了第 4 次

执行了第 5 次

执行了第 6 次

执行了第 7 次

执行了第 8 次

执行了第 9 次

执行了第 10 次

线程2执行了...

Java中volatile和synchronized的区别

volatile是为了保证变量的可见性的,是比较轻量级的,而synchronized关键字是比较重量级的。synchronized能实现非原子性操作的线程安全,而volatile实现不了,比如下面这段代码,只能用synchronized来实现:

public synchronized int getA() {

return a++;

}

public synchronized int getNext() {

return value ++;

}

就是说synchronized能实现所有volatile能实现的功能,而volatile对资源的消耗比较小。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值