【Java并发入门】03 互斥锁(上):解决原子性问题()

  本篇文章为你整理了【Java并发入门】03 互斥锁(上):解决原子性问题()的详细内容,包含有 【Java并发入门】03 互斥锁(上):解决原子性问题,希望能帮助你了解 【Java并发入门】03 互斥锁(上):解决原子性问题。

  Q:如果禁用 CPU 线程切换是不是就解决这个问题了?

  A:单核 CPU 可行,但到了多核 CPU 的时候,有可能是不同的核在处理同一个变量,即便不切换线程,也有问题。

  所以,解决原子性的关键是「同一时刻只有一个线程处理该变量,也被称为互斥」。

  如何做到呢?用「锁」。

  
原子性问题的源头是线程切换

  Q:如果禁用 CPU 线程切换是不是就解决这个问题了?
 

  A:单核 CPU 可行,但到了多核 CPU 的时候,有可能是不同的核在处理同一个变量,即便不切换线程,也有问题。

  所以,解决原子性的关键是「同一时刻只有一个线程处理该变量,也被称为互斥」。

  如何做到呢?用「锁」。

  一、锁模型

  一)简易锁模型

  一般看到的锁模型长下面这样。

  但对于这个模型,会有几个疑问:

  锁的是什么?

  临界区的这一堆代码相关的都被锁了?

  保护的又是什么?

  二)改进后的锁模型

  用下面这个模型来解释就解答了上面几个问题:

  要保护的是临界区中的资源 R

  因此要为 R 创建一个对应的锁 LR

  需要处理资源 R 的时候先加锁,处理完之后解锁

  要注意的是:

  一个资源必须和锁对应,不能用 A 锁去锁 B 资源

  二、Java 提供的锁技术

  Java 提供了多种技术,这里仅谈及 Synchronized。

  Synchronized 关键字

  Java 语言提供的 synchronized 关键字,就是锁的一种实现。synchronized 关键字可以用来修饰方法,也可以用来修饰代码块。

  

class X {

 

   // 修饰非静态方法

   synchronized void foo() {

   // 临界区

   // 修饰静态方法

   synchronized static void bar() {

   // 临界区

   // 修饰代码块

   Object obj = new Object();

   void baz() {

   synchronized(obj) {

   // 临界区

  

 

  Q:synchronized 没看到 lock 和 unlock?
 

  A:在编译的时候会做转换,synchronized起始的地方加锁,结束的地方解锁。

  Q:那么 synchronized 锁的是什么呢?
 

  A:当修饰静态方法时,锁定的是当前类的 Class 对象,在上面的例子中就是 Class X;
 

  当修饰非静态方法时,锁定的是当前实例对象 this。
 

  当修饰代码块时,括号中写的是啥就锁啥。

  (可能不准确)
 

  Class 对象是用来保存类信息的,可以理解为元数据?
 

  实例对象则是每一个 new 出来的特殊的个体

  Synchronized 实例

  

public class SynchronizedTT {

 

   private int value = 0;

   //public void printValue() {

   public synchronized void printValue() {

   System.out.println(this.value);

   public synchronized void addValue() throws InterruptedException {

   Thread.sleep(1000);

   this.value += 1;

  // 开两个线程,一个先调用 addValue(),另一个后调用 printValue()

  

 

  

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: