synchronized和volatile

要想实现内存可见性必须要做的两个步骤:
1)线程修改后的共享变量能够及时从线程本地内存刷新到主内存
2)其他线程能够及时把共享变量的最新值从主内存更显到自己的工作内存中

synchronized保证synchorized{}范围内的操作的原子性和共享数据的可见性

synchronized保证操作的原子性是添加互斥锁。在{}中锁的获取和释放是隐私的。

synchronized的内存可见性步骤:
1)获取互斥锁
2) 清空工作内存
3)从主内存拷贝变量的最新值到工作内存中
4)执行代码
5)将更改后的共享变量值刷新到主内存中
6)释放互斥锁

volatile保证内存可见性
volatile int a;
假设线程A修改了共享变量a,并把它刷新到主内存中。线程B需要读取a时,首先把线程本地内存中的a变量置为无效,然后从主内存中读取a的最新值。这也算是线程通过共享内存间接通信了。

volatile只能保证可见性,不能保证原子性。
这句话该如何理解呢?

看Demo

class VolatileExample {
int a = 0;
volatile boolean flag = false;
public void writer() {
    a = 1;        // 1
    flag = true;   // 2
    }
public void reader() {
    if (flag) {    // 3
    int i = a;      // 4
    ……
    }
    }
}//线程A调用writer(),线程B调用reader()

在多线程并发时,线程切换时不可预测的,假设线程A操作还没有执行到a=1时,切换到线程B,结果线程B没有执行if语句,这样线程通信就失败了。volatile不能保证原子性是应为线程的交叉执行。

问:为什么不加synchorized和volatile,共享变量在多个线程中也可见?

答:是处理器或者说是JMM(java 内存模型)在不断刷新线程工作空间的值和主内存中的值。加上synchronized和volatile更安全。

线程的分类:守护线程(GC)和用户线程(main线程)
使用setDaemon(boolean)可以设置线程为守护线程

Thread.State是枚举类型,描述线程的状态:
new
running
blocking
waiting
timed-waiting
terminated

jdk/bin 目录下的jstack更够帮你生成jvm中所有线程的快照

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值