volatile既然不足以保证数据同步,那么就必须要引入锁来确保。互斥锁是最常见的同步手段,在并发过程中,当多条线程对同一个共享数据竞争时,它保证共享数据同一时刻只能被一条线程使用,其他线程只有等到锁释放后才能重新进行竞争。对于java开发人员,我们最熟悉的肯定就是用synchronized关键词完成锁功能,在涉及到多线程并发时,对于一些变量,你应该会毫不犹豫地加上synchronized去保证变量的同步性。

在C/C++可直接使用操作系统提供的互斥锁实现同步和线程的阻塞和唤起,与之不同的是,java要把这些底层封装,而synchronized就是一个典型的互斥锁,同时它也是一个JVM级别的锁,它的实现细节全部封装在JVM中实现,对开发人员只提供了synchronized关键词。根据锁的颗粒度,可以用synchronized对一个变量、一个方法、一个对象和一个类等加锁。被synchronized修饰的程序块经过编译后,会在前后生成monitorenter和monitorexit两个字节码指令,其中涉及到锁定和解锁对象的确定,这就要根据synchronized来确定了,假如明确指定了所对象,例如synchronized(变量)、synchronized(this)等,说明加解锁对象为变量或运行时对象。假如没有明确指定对象,则根据synchronized修饰的方法去找对应的锁对象,如修饰一个非静态方法表示此方法对应的对象为锁对象,如修饰一个静态方法则表示此方法对应的类对象为锁对象。当一个对象被锁住时,对象里面所有用synchronized修饰的方法都将产生堵塞,而对象里非synchronized修饰的方法可正常被调用,不收锁影响。

为了实现互斥锁,JVM的monitorenter和monitorexit字节码依赖底层操作系统的互斥锁来实现,java层面的线程与操作系统的原生线程有映射关系,这时如果要将一个线程进行阻塞或唤起都需要操作系统的协助,这就需要从用户态切换到内核态来执行,这种切换代价十分昂贵,需要消耗很多处理器时间。如果可能,应该减少这样的切换,jvm一般会采取一些措施进行优化,例如在把线程进行阻塞操作之前先让线程自旋等待一段时间,可能在等待期间其他线程已经解锁,这时就无需再让线程执行阻塞操作,避免了用户态到内核态的切换。

Synchronized还有另外一个重要的特性——可重入性。这个特性主要是针对当前线程而言的,可重入即是自己可以再次获得自己的内部锁,在尝试获取对象锁时,如果当前线程已经拥有了此对象的锁,则把锁的计数器加一,在释放锁时则对应地减一,当锁计数器为0时表示锁完全被释放,此时其他线程可对其加锁。可重入特性是为了解决自己锁死自己的情况,如下面伪代码:

public class DeadLock{

public synchronized void method1(){}

public synchronized void method2(){

this.method1();

}

public static void main(String[] args){

DeadLock deadLock=new DeadLock();

deadLock.method2();

}

}

这种情况其实也并非不常见,一个类中的同步方法调用另一个同步方法,假如synchronized不支持重入,进入method2方法时当前线程将尝试获取deadLock对象的锁,而method2方法里面执行method1方法时,当前线程又要去尝试获取deadLock对象的锁,这时由于不支持重入,它要去等deadLock对象的锁释放,把自己阻塞了,这就是自己锁死自己的现象。所以重入机制的引入,杜绝了这种情况的发生。

synchronized实现的是一个非公平锁,非公平主要表现在获取锁的行为上,并非是按照申请锁的时间前后给等待线程分配锁的,每当锁被释放后,任何一个线程都有机会竞争到锁,这样做的目的是为了提高执行性能,当然也会产生线程饥饿现象。

synchronized最后一个特性(缺点)就是不可中断性,在所有等待的线程中,你们唯一能做的就是等,而实际情况可能是有些任务等了足够久了,我要取消此任务去干别的事情,此时synchronized是无法帮你实现的,它把所有实现机制都交给了JVM,提供了方便的同时也体现出了自己的局限性。

这节主要介绍java的synchronized关键词,包括它的作用及JVM及操作系统的底层实现,它的可重入性和不可中断性,它实现的是一个非公平的互斥锁,同时它也是一个悲观的并发策略,不管是否会产生竞争,任何的数据操作都必须要加锁。对synchronized深入全面的理解对理解tomcat中跟多线程并发相关的模块是很有帮助的。

喜欢研究java的同学可以交个朋友,下面是本人的微信号:

悲观的并发策略——Synchronized互斥锁的更多相关文章

  1. python 并发编程 多进程 互斥锁 目录

    python 并发编程 多进程 互斥锁 模拟抢票 互斥锁与join区别

  2. synchronized互斥锁实例解析

    目录 synchronized互斥锁实例解析 1.互斥锁基础使用:防止多个线程同时访问对象的synchronized方法. 1.1.多个线程调用同一个方法 1.2.多个线程多个锁,升级为类锁 2.线程 ...

  3. c++并发编程之互斥锁(mutex)的使用方法

    1. 多个线程访问同一资源时,为了保证数据的一致性,最简单的方式就是使用 mutex(互斥锁). 引用 cppreference 的介绍: The mutex class is a synchroni ...

  4. Golang之并发资源竞争(互斥锁)

    并发本身并不复杂,但是因为有了资源竞争的问题,就使得我们开发出好的并发程序变得复杂起来,因为会引起很多莫名其妙的问题. package main import ( "fmt" &q ...

  5. python 并发编程 多线程 互斥锁

    互斥锁 并行变成串行,牺牲效率 保证数据安全,实现局部串行 保护不同的数据,应该加不同的锁 现在一个进程 可以有多个线程 所有线程都共享进程的地址空间 实现数据共享 共享带来问题就会出现竞争 竞争就会 ...

  6. python 并发编程 多进程 互斥锁与join区别

    互斥锁与join 互斥锁和join都可以把并发变成串行 以下代码是用join实现串行 from multiprocessing import Process import time import js ...

  7. python 并发编程 多进程 互斥锁

    运行多进程  每个子进程的内存空间是互相隔离的 进程之间数据不能共享的 一 互斥锁 但是进程之间都是运行在一个操作系统上,进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终 ...

  8. C++ 并发编程之互斥锁和条件变量的性能比较

    介绍 本文以最简单生产者消费者模型,通过运行程序,观察该进程的cpu使用率,来对比使用互斥锁 和 互斥锁+条件变量的性能比较. 本例子的生产者消费者模型,1个生产者,5个消费者. 生产者线程往队列里放 ...

  9. 并发编程 Process 互斥锁

    进程理论 程序与进程的区别 ''' 程序不是存在硬盘上的代码,相对来说是静态的 进程表示程序在执行的过程,是动态的 ''' 进程的调度 先来先服务调度算法 '''对长作业有利,对短作业无益''' 短作 ...

随机推荐

  1. 【Python3.6+Django2.0+Xadmin2.0系列教程之二】学生信息管理系统(入门篇)

    上一篇我们已经创建好了一个Xadmin的基础项目,现在我们将在此基础上构建一个同样很基础的学生信息管理系统. 一.创建模型 模型是表示我们的数据库表或集合类,并且其中所述类的每个属性是表或集合的字段, ...

  2. 机器学习基石:05 Training versus Testing

    train:A根据给定训练集D在H中选出g,使得Ein(g)约等于0: test:g在整个输入空间X上的表现要约等于在训练集D上的表现,使得Eout(g)约等于Ein(g). 如果|H|小,更易保证t ...

  3. Junit简单配置

    Junit简单配置的步骤如下: 1.在WEB-INF目录下的lib里面放一个junit包,我用的是junit-4.9.jar: 2.选定要测试的类,右键单击该类,新建一个Junit Test Case ...

  4. TF-IDF In Scikit-Learn

    TF-IDF In Scikit-Learn 2017年9月30日补充   其实在算下面TF-IDF的步骤之前,还有一步,就是计算Term Frequency 也就是词频.当然,scikit-lear ...

  5. [SCOI 2009]windy数

    Description 题库链接 找出在 \([A,B]\) 间满足相邻位差值至少为 \(2\) 的正整数个数. \(1\leq A,B\leq 2\cdot 10^9\) Solution 数位 \ ...

  6. BZOJ4894 天赋

    Description 小明有许多潜在的天赋,他希望学习这些天赋来变得更强.正如许多游戏中一样,小明也有n种潜在的天赋,但有 一些天赋必须是要有前置天赋才能够学习得到的.也就是说,有一些天赋必须是要在 ...

  7. [Ahoi2005]LANE 航线规划

    题目描述 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系——一个巨大的由千百万星球构成的Samuel星系. 星际空间站的Samuel II巨型计算 ...

  8. bzoj 5288: [Hnoi2018]游戏

    Description Solution 乱搞能A的题,毁我青春 记忆化一下扩展过程 只要不是从 \(1\) 枚举到 \(n\) 去扩展都可以 \(AC\) 于是 \(random\_shuffle\ ...

  9. poj 3348 Cow 凸包面积

    Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8122   Accepted: 3674 Description ...

  10. [bzoj4763]雪辉&[bzoj4812][Ynoi2017]由乃打扑克

    来自FallDream的博客,未经允许,请勿转载,谢谢. cut掉部分题面. 给一个n个点的树,点有点权,有m次询问,每次询问多条链的并有多少种不同的点权以及它的mex mex就是一个集合中最小的没有 ...