Java并发编程实战 第一部分 基础知识(一)线程安全性

忘是亡心i 2024-04-18 16:32 120阅读 0赞

线程安全性

一个对象是否需要是线程安全的,取决于它是否被多个线程访问。这指的是在程序中访问对象的方式,而不是对象要实现的功能。要使得对象是线程安全的,需采用同步机制来协同对对象可变状态的访问。
当多个线程访问某个状态变量并且其中有一个线程执行写入操作时,必须采用同步机制来协同这些线程对变量的访问。Java中主要同步机制关键字synchronized,提供一种独特的加锁方式,但同步还包括volatile类型的变量,显示锁以及原子变量。
当多个线程访问同一个可变的状态变量时没有同步,那么程序就会出错。有3种方法解决

  1. 不在线程之间共享该状态变量。
  2. 将该状态变量修改为不可变的变量。
  3. 在访问该变量时使用同步。

什么是线程安全

当多个线程访问某个类时,不管运行时采用何种调度方式或者线程实如何叫体制性的,并且在代码中不需要额外的同步和协同,这个类能表现出正确的行为,那么就称这个类是线程安全的。
在线程安全类种封装了同步机制,所以无需进一步采用同步措施。
无状态对象一定是线程安全的。

原子性

假设有两个操作A和B,从执行A的线程来看,当另一个线程执行B时,要么B全部执行完,要不完全不执行B,那么A和B对彼此来说是原子的。原子造作是指,对于访问同一个状态的所有操作(包括该操作本身)来说,这个操作是一个以原子方式执行的操作。
在实际情况在,尽可能使用现有的线程安全对象(例如java.util.concurrent.atomic包种包含了一些原子变量类,AtomicLong)来管理类的状态。与非线程安全的对象相比,判断线程安全对象的可能状态及其状态转换情况要更为容易,从而也更容易维护和验证线程安全性。

加锁机制

Java提供了一种内置的锁机制来支持原子性:同步代码块(synchronized block)。
同步代码块包括两部分:一个作为锁的对象引用,一个作为由这个锁保护的代码块。
静态的synchronized方法以Class对象作为锁。
每个Java对象都可以用做一个实现同步的锁,这些锁被称为内置锁。线程在进入同步代码块自动获得锁,退出同步代码块自动释放锁。
两个方法可以退出:1.正常退出,即执行完毕。2.抛出异常退出。
获取锁的唯一途径就是进入同步代码块。
重入:内置锁是可重入的,如果某个线程请求一个已经由它自己持有的锁,那么这个请求就会成功。
重入的一种实现方式:为每个锁关联一个计数值和一个所有者线程,当计数值为0时,说明该锁没有被任何线程持有,当一个线程请求一个没有被持有的锁,JVM就会几下锁的持有者,并且计数值+1,如果同一个线程再次请求这个锁,再+1,当退出,即-1,当计数值为0,释放锁。

发表评论

表情:
评论列表 (有 0 条评论,120人围观)

还没有评论,来说两句吧...

相关阅读