java synchronization_关于java中的synchronization与volatile关键字

关于java中的synchronization与volatile关键字

关于java中的synchronization与volatile关键字

java中的同步是用关键字synchronized和volatile实现

在java中,我们不能使用syncchronized去修饰变量,用synchronized去修饰变量是非法的。我们可以用volatile代替synchronized去修饰变量,volatile会通知JVM从主内存读取变量而不是从cache中读取。

如果一个变量并没有在多线程中共享,那么就不要使用volatile

使用volatile修饰的变量,这个变量的改变对每个线程都是可见的,一旦改变,其它线程会立刻知道。

5.

volatile使用示例

public class Singleton {

private static volatile Singleton instance;

private Singleton() {

// do something to prevent from reflection

}

public static Singleton getInstance() {

if (instance == null) {

synchronized(Singleton.class) {

if (instance == null) {

instance = new Singleton();

}

}

}

return instance;

}

}

在以上的示例中使用了懒加载的单例。如果我们没有使用volatile修饰instance,那么正在创建instance的thread即使创建了instance也不能通知到其它线程。例如:当threadA刚刚创建完instance,cpu切换了线程,那么其它的线程并不知道instance已经创建了,还会认为instance是null;

为什么呢?因为等待的线程并没有进行任何锁定,直到拥有锁的线程从同步块出来,在这个瞬间,线程间的内存将不会同步,并且instance的值不会在主内存中更新。 使用Java中的volatile关键字,Java会自己处理,让所有的线程都可以看到这些更新。

来张内存示意图

8f50928cd0c7deabcb7f88e056cc8ef1.png

volatile并不能保证变量值是多线程同步的

public class Test {

public volatile int inc = 0;

public void increase() {

inc++;

}

public static void main(String[] args) {

final Test test = new Test();

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

new Thread(){

public void run() {

for(int j=0;j<1000;j++)

test.increase();

};

}.start();

}

while(Thread.activeCount()>1) //保证前面的线程都执行完

Thread.yield();

System.out.println(test.inc);

}

}

大家想一下这段程序的输出结果是多少?也许有些朋友认为是10000。但是事实上运行它会发现每次运行结果都不一致,都是一个小于10000的数字。

可能有的朋友就会有疑问,不对啊,上面是对变量inc进行自增操作,由于volatile保证了可见性,那么在每个线程中对inc自增完之后,在其他线程中都能看到修改后的值啊,所以有10个线程分别进行了1000次操作,那么最终inc的值应该是1000*10=10000。

这里面就有一个误区了,volatile关键字能保证可见性没有错,但是上面的程序错在没能保证原子性。可见性只能保证每次读取的是最新的值,但是volatile没办法保证对变量的操作的原子性。

使用示例

下面列举几个Java中使用volatile的几个场景。

1.状态标记量

volatile boolean flag = false;

while(!flag){

doSomething();

}

public void setFlag() {

flag = true;

}

volatile boolean inited = false;

//线程1:

context = loadContext();

inited = true;

//线程2:

while(!inited ){

sleep()

}

doSomethingwithconfig(context);

2.double check

class Singleton{

private volatile static Singleton instance = null;

private Singleton() {

}

public static Singleton getInstance() {

if(instance==null) {

synchronized (Singleton.class) {

if(instance==null)

instance = new Singleton();

}

}

return instance;

}

}

关于java中的synchronization与volatile关键字相关教程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值