首页IT科技java并发的时候常用的处理方式(【Java并发入门】03 互斥锁(上):解决原子性问题)

java并发的时候常用的处理方式(【Java并发入门】03 互斥锁(上):解决原子性问题)

时间2025-05-02 12:51:04分类IT科技浏览3271
导读:原子性问题的源头是线程切换...

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

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()

?思考:如果 printValue() 不添加 synchronized 关键字      ,会造成什么样的结果?

A:有可能会先执行了 addValue 在执行 print 但得到的却是增加之前的数值                。

三     、锁和受保护资源的关系

要点:

一把锁可以保护多个资源 但是一个资源只能用一把锁保护 受保护资源和锁之间的关联关系是 N:1 的关系

?思考:如果用多把锁锁同一个资源会出现什么情况?

下面例子:

synchronized 是不同的锁     ,就和没锁一样           。 public class SynchronizedTT { private static int value = 0; public synchronized void printValue() { System.out.println(value); } public synchronized static void addValue() throws InterruptedException { Thread.sleep(1000); value += 1; } }

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
mac 复制文件夹路径(Mac中复制文件路径最简单、最快速的方法) 联想自带系统光盘重装系统(如何使用联想随机操作系统恢复光盘安装Windows XP的图文方法)