`
lisaiori
  • 浏览: 15086 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

JAVA 并发编程-基础

 
阅读更多

并发编程实际就是多线程并发编程。

 

程序在多线程环境下运行时,如果多个线程同步访问相同的共享对象,就可能会出现线程安全性问题。

 

影响线程安全性的原因有两个:原子性可见性

 

原子性:可以参考事务的逻辑模型,或者程序处理中的复合操作(如:“先检查-后执行”以及“读取-修改-写入”等操作统称为复合操作:包含了一组必须以原子方式执行的操作以确保线程安全性)。

可见性:确保当一个线程修改了对象状态后,其他线程能够看到发生的状态变化。(影响可见性的原因:如JVM的重排序、失效数据、非原子的64位操作、-server/-client  JVM参数);

在不进行的显式线程安全控制的程序中,处于多线程并发运行时,原子性和可见性是不能保证的。

---------------------------------------------------------------------------------------------------------------------------------

JAVA提供的解决方案:

内置锁

Java提供了一种内置的锁机制来支持原子性:同步代码块 Synchronized Block。同步代码块包括两部分:一个作为锁的对象引用;一个作为由这个锁保护的代码。

以关键字synchronized 来修饰的方法就是一种横跨整个方法体的同步代码块,其中该同步代码块的锁就是方法调用所在的对象。静态的synchronized 方法以Class 对象作为锁。(注意:synchronized  修饰基本类型包装类的时候,基本类型的包装类 ++运算之后会 new 出新的对象实例,会导致多个线程之间,锁对象变为不是同一个);

另外,加锁的含义不仅仅局限于互斥行为,还包括内存可见性。为了确保所有线程都能看到共享变量的最新值,所有执行读操作或写操作的线程都必须在同一个锁上同步。

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

---------------------------------------------------------------------------------------------------------------------------------

 

volotile变量
当把变量什么为volatile类型后,编译器与运行时都会注意到这个变量是共享的,因此不会将该变量上的操作与其他内存操作一起重新排序。volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在读取volatile类型的变量时总会返回最新写入的值。简单来理解,就是通过volotile关键字,能够解决多线程之间可见性的问题。

然而,在访问volatile变量时,不会执行加锁操作,因此也就不会使执行线程阻塞,因此volatlie变量是一种比synchronized关键字更轻量级的同步机制。

仅当volatile变量能简化代码的实现以及对同步策略的验证时,才应该使用它们。如果在验证正确性时需要对可见性进行复杂的判断,那么就不要使用volatile变量。volatile变量的正确使用方式包括:确保它们自身状态的可见性,确保它们所引用对象的状态可见性,以及标识一些重要的程序生命周期事件的发生(例如,初始化或关闭)。使用volatile的原则:
    a、对变量的写入操作不依赖变量的当前值,或者你能确保只有单个线程更新变量的值
    b、改变量不会与其他状态变量一起纳入不变性条件
    c、在访问变量时不需要加锁

---------------------------------------------------------------------------------------------------------------------------------

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics