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. [Jsoi2011]分特产

    Description JYY 带队参加了若干场ACM/ICPC 比赛,带回了许多土特产,要分给实验室的同学们. JYY 想知道,把这些特产分给N 个同学,一共有多少种不同的分法?当然,JYY 不希望 ...

  2. ●BZOJ 3963 [WF2011]MachineWorks

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3963 题解: 斜率优化DP,CDQ分治. 先按时间排序.(规定以下内容的第i台机器的卖出时间 ...

  3. poj 3335 Rotating Scoreboard(半平面交)

    Rotating Scoreboard Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 6420   Accepted: 25 ...

  4. poj 1269 线段与线段相交

    Intersecting Lines Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 13605   Accepted: 60 ...

  5. hdu 3473 划分树

    Minimum Sum Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Tot ...

  6. 使用jquery.qrcode.js生成二维码

    通常生成二维码的方式有两种:第一种是java代码的形式,第二种是通过Js方式. 在这里我做个记录,用js生成二维码,可以在官网下载源码:http://jeromeetienne.github.io/j ...

  7. spine - unity3D(摘自博主softimagewht)

    摘自:(博主 http://www.cnblogs.com/softimagewht/p/4149118.html) //skeletonDataSkeletonAnimation skeletonA ...

  8. mysql免安装版下载及配置教程

    第一步:下载 下载地址:http://dev.mysql.com/downloads/mysql/ 滚动到下方就能看到了,根据自己的需求下载: 我的电脑为64为的所以下载的为 Windows (x86 ...

  9. 利用maven install jar到项目当中

    接着上面利用maven打好的jar包.把刚刚打好的包放入其他项目当中怎么办? 只需要在相同的目录下执行mvn install,maven会自动把jar放到本地仓库中. 这样,原先maven项目中缺少依 ...

  10. 两个对象用equals方法比较为true,它们的Hashcode值相同吗?

    两个对象用equals方法比较为true,它们的Hashcode值相同吗? 答:不一定相同.正常情况下,因为equals()方法比较的就是对象在内存中的值,如果值相同,那么Hashcode值也应该相同 ...