《Java并发编程实战》第二章笔记

第一部分

  1. 一个对象是否需要是线程安全的,取决于它是否被多个线程访问。这值得是在程序中访问对象的方式,而不是对象要实现的功能。
  2. 当多个线程访问某个状态变量并且其中有一个线程执行写入操作时,必须采用同步机制来协同这些线程对变量的访问。
  3. 如果当多个线程访问同一个可变的状态变量时没有使用适合的同步,那么程序就会出现错误。有3种方式可以修复这个问题:
  • 不在线程之间共享该状态变量
  • 将状态变量修改为不可变变量
  • 在访问状态变量时使用同步
  1. 无状态对象一定是线程安全的。

  2. 内置锁
    JAVA提供了一种内置的锁机制来支持原子性:同步代码块(synchronized block)。
    同步代码包括两部分:一个作为锁的对象引用,一个作为由这个锁保护的代码块。
    java的内置锁相当于一个互斥体,这个意味着最多只有一个线程能持有这种锁。当线程A尝试获取一个由线程B持有的锁时,线程A必须等待或者阻塞,直到线程B释放这个锁.如果B永远不释放锁,那么A也永远等待下去。

  3. 重入
    重入的一种实现方式是:为每个锁关联一个获取计数值和一个所有者线程,当计数值为0时,这个锁就被认为是没有被任何线程持有。当线程请求一个未被持有的锁时,jvm将记下锁的持有者,并且将获取计数值置为1.如果同一个线程再次获取这个锁,计数值将递增,而当线程退出同步代码块时,计数器会相应的递减,当计数值为0是,这个锁将释放。

  4. 内置锁是可重入的。因此当某个线程试图获取一个已经由它自己持有的锁, 那么这个请求就会成功。
    一段有问题的代码
    该servlet在没有足够原子性保证的情况下对其最近计算结果进行缓存

    该servlet在没有足够原子性保证的情况下对其最近计算结果进行缓存.png

这个servelt能正确的缓存最近计算结果,但并发性却非常糟糕


这个servelt能正确的缓存最近计算结果,但并发性却非常糟糕.png

如果内置锁不是可重入的,那么这段代码将发生死锁

image.png

如果内置锁不是可重入的,那么在调用super.dosomething时,将无法获得Widget上的锁。因为这个锁已经被持有,从而线程将永远停顿下去,等待一个永远也无法获得的锁,重入则避免了这种死锁情况的发生。

你可能感兴趣的:(《Java并发编程实战》第二章笔记)