博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
互斥锁 synchronized分析
阅读量:4292 次
发布时间:2019-05-27

本文共 2020 字,大约阅读时间需要 6 分钟。

开头:

互斥锁是为了保证同一个方法同时间只有一个线程去执行,这个也是在多线程开发当中最基本的实现。在java体系当中有很多方法可以实现目的,如: synchronized ,lock ,redis分布式锁,zk分布式锁,基于数据库实现悲观锁等等。 本文将介绍synchronized这个java原生支持的互斥锁。

简易的锁模型

在这里插入图片描述

我们把一段需要互斥的代码称为:临界区。 当线程需要进入临界区的时候,线程需要去尝试获取锁,当获取成功之后就进去临界区执行代码,执行结束之后就去释放锁。 如果在获取线程的时候,其他线程正在使用锁,就会阻塞等待。

使用方法

class X {  // 修饰非静态方法  synchronized void foo() {    // 临界区  }  // 修饰静态方法  synchronized static void bar() {    // 临界区  }  // 修饰代码块  Object obj = new Object();  void baz() {    synchronized(obj) {      // 临界区    }  }}

这段代码示例中没有出现加锁和解锁的方法,他们的实现是由java编译器在synchronized修饰的方法或者代码块前后自动加上的。

synchronized使用时候有以下几条规则:

  1. 当修饰静态方法的时候,锁定的是当前类的Class对象,在上面的例子 就是Class X.
  2. 当修饰非静态方法的时侯,锁定的是当前实现对象this。

示例: 用synchronized解决 count+=1问题

MyCalc这个类有两个方法:一个是get()方法,用来获取value的值;另一个是addOne()方法,用来给value加1,并且addOne()方法我们用Synchronized修饰。

class SafeCalc {  long value = 0L;  long get() {    return value;  }  synchronized void addOne() {    value += 1;  }}

因为addOne()方法被synchronized修饰之后,这个方法就会同时只有一个线程去执行,所以一定能保证原子操作。因为我们的value方法是成员变化,会不会有线程可见性问题呢?

这里就会出来另一个概念: 管程与管程中锁的规则

1. 管程: 就是我们这里的synchronized。

2. 管程中锁的规则: 对一个锁的解锁 Happens-before 做用于后续这个锁的加锁。
第二句话的意思是指 前一个线程的解锁操作对后一个线程的加锁操作是可见的,综合Happens-before的传递性规则,我们就得出前一个线程在临界区修改的共享变更(该操作在解锁之前),对后续进入临界区(该操作在加锁之后)的线程是可见的。

按照这个规则,如果多个线程同时操作addOne()这个方法, 可见性是可以保证的,也就是说如果有100 个线程去执行addOne()这个方法,最终的value的结果会是增加了100。

但是此时还是有一个问题,get()我方法的可见性是无法保证的。管程中锁的规则,是只保证后续对这个锁的加锁的可见性,而get()方法并没有加锁操作。所以可见性是无法保证的。我们可以通过给get() 方法加上synchronized修饰来保证可见性。

class SafeCalc {  long value = 0L;  synchronized long get() {    return value;  }  synchronized void addOne() {    value += 1;  }}

更改后的模型:

在这里插入图片描述

错误方式

package com.bdf.blog.thread.Synchronized;/** * @program: blog * @description: * @author: canghaihongxin * @create: 2019-04-21 12:24 **/public class SafeCacl {    static int value ;    public synchronized int getValue() {        return value;    }    public synchronized static void addOne(){        value +=1;    }}

这样就是一个错误的代码示例, 当我们在addOne()方法上添加了static 关键字的时候就Synchronized锁的就是我SafeCacl.class这个类,也就是类锁。synchronized锁的是this。

这个时候getValue()方法就无法保证可见性了。
在这里插入图片描述

转载地址:http://gjkws.baihongyu.com/

你可能感兴趣的文章
UIViewController小结
查看>>
iOS 多线程小结
查看>>
AVFoundation 框架小结
查看>>
CGTime CMTimeRange CMTimeMapping 小结
查看>>
UIView 小结
查看>>
iOS OpenGL ES Guide
查看>>
iOS OpenGL ES 术语
查看>>
iOS Stream
查看>>
AFNetworking 框架小结 一(AFURLRequestSerialization)
查看>>
AFNetworking 框架小结 二(AFURLResponseSerialization)
查看>>
MVVM 框架简介
查看>>
iOS 内存简介
查看>>
TargetConditionals 文件解析
查看>>
iOS 运行时方法列表
查看>>
判断视图是否相交
查看>>
LLDB 常用命令
查看>>
项目啊,不存在的
查看>>
Open GL ES 编程基础(一)
查看>>
Open GL ES 编程基础(二)
查看>>
OpenGL ES 编程基础(三)
查看>>