《Java并发编程实战》---线程安全性---加锁

1:原子性与可见性

1.1原子性

具有原子性的操作被称为原子操作。原子操作在操作完毕之前不会线程调度器中断。在Java中,对除了long和double之外的基本类型的简单操作都具有原子性。简单操作就是赋值或者return。比如”a = 1;“和 “return a;”这样的操作都具有原子性。但是在Java中,上面买碘片例子中的类似”a += b”这样的操作不具有原子性,所以如果add方法不是同步的就会出现难以预料的结果。在某些JVM中”a += b”可能要经过这样三个步骤:取出a和b计算a+b将计算结果写入内存如果有两个线程t1,t2在进行这样的操作。t1在第二步做完之后还没来得及把数据写回内存就被线程调度器中断了,于是t2开始执行,t2执行完毕后t1又把没有完成的第三步做完。这个时候就出现了错误,相当于t2的计算结果被无视掉了。所以上面的买碘片例子在同步add方法之前,实际结果总是小于预期结果的,因为很多操作都被无视掉了。类似的,像”a++“这样的操作也都不具有原子性。

1.2可见性

在可共享内存的多处理器体系架构中,每个处理器都有它自己的缓存,并且周期性地与主存协调一致。处理器架构提供了不同级别的缓存一致性;有些只提供了最小的保证,几乎在任何时间内,都允许不同的处理器在相同的存储位置上看到不同的值。因此,上面的程序中,当一个线程调用set方法后,并不能保证当另一个线程获取value的值时,value的值已经同步到主存中,获取到的任然可能是旧值

在没有同步的情况下,编译器、处理器以及运行时等都可能对操作的执行顺序进行一些意想不到的调整。在缺乏足够线程同步的多线程程序中,想要对内存操作的执行顺序进行判断,几乎无法得出正确结论;
java内存模型要求,变量的读取操作和写入操作都必须是原子操作,但是对于非volatile的long和double变量,JVM允许将64位的读写操作分解为两个32位的操作;当读取一个非volatile类型的long变量时,如果读操作和写操作不在一个线程中,那么很可能会读取到某个值的高32位和另一个值的低32位;

对long和double的简单操作不具有原子性。但是,一旦给这两个类型的属性加上volatile修饰符,对它们的简单操作就会具有原子性(当然这是说的在Java SE5之后的故事)。在一些情况下即便是原子操作也可能会引发一些错误,特别是在多处理器的环境下。因为多处理器的计算机可以将内存中的值暂时储存在寄存器或者本地内存缓冲区中。所以,运行在不同处理器上的线程取同一个内存位置的值可能不相同。有一些编译器也会自作主张地优化指令,使得上述情况发生。你当然可以用同步锁来解决这些问题,不过volatile也能解决。如果给一个变量加上volatile修饰符,就相当于:每一个线程中一旦这个值发生了变化就马上刷新回主存,使得各个线程取出的值相同。编译器不要对这个变量的读、写操作做优化。但是值得注意的是,除了对long和double的简单操作之外,volatile并不能提供原子性。所以,就算你将一个变量修饰为volatile,但是对这个变量的操作并不是原子的,在并发环境下,还是不能避免错误的发生!

原子性问题和可见性问题会导致线程安全问题,需要保证原子性和可见性;

2:内置锁

Java提供了一种内置锁机制来支持原子性:同步代码块;内置锁也支持了可见性;

每个java对象都可以用作一个实现同步的锁,这个锁被称为内置锁或者监视器锁。

Java的内置锁相当于一种互斥体(或者互斥锁),这意味着最多只有一个线程持有这个锁;

由于每次只能有一个线程执行内置锁保护的代码块,因此由这个锁保护的同步代码块会以原子方式执行,多个线程在执行该代码块时也不会相互干扰。

3:重入

当某个线程请求一个由其他线程持有的锁时,发出请求的线程就会阻塞。然而由于内置锁是可重入的,如果某个线程试图获取一个已经由他持有的锁,那么这个请求就会成功;

例如,子类改写了父类的方法,都需要对方法synchronzed,子类方法又要调用父类的方法,这时候就体现了内置锁的可重入性;


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值