一、synchronized 的介绍

  synchronized 是 Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码,而这段代码也被称为临界区。

  synchronized 有多个叫法,而每个叫法都表明synchronized 的特性:

1、内置锁(又叫 隐式锁):synchronized 是内置于JDK中的,底层实现是native;同时,加锁、解锁都是JDK自动完成,不需要用户显式地控制,非常方便。

2、同步锁:synchronized 用于同步线程,使线程互斥地访问某段代码块、方法。这就是意味着最多只有一个线程能够获得该锁,当线程A尝试去获得线程B持有的内置锁时,线程A必须等待或者阻塞,知道线程B释放这个锁,如果B线程不释放这个锁,那么A线程将永远等待下去。

3、对象锁:准确来说,是分为对象锁、类锁。synchronized 以当前的某个对象为锁,线程必须通过互斥竞争拿到这把对象锁,从而才能访问 临界区的代码,访问结束后,就会释放锁,下一个线程才有可能获取锁来访问临界区(被锁住的代码区域)。synchronized锁 根据锁的范围分为 对象锁 和 类锁。对象锁,是以对象实例为锁,当多个线程共享访问这个对象实例下的临界区,只需要竞争这个对象实例便可,不同对象实例下的临界区是不用互斥访问;而类锁,则是以类的class对象为锁,这个锁下的临界区,所有线程都必须互斥访问,尽管是使用了不同的对象实例;

总的来说,对象锁的粒度要比类锁的粒度要细,引起线程竞争锁的情况比类锁要少的多,所以尽量别用类锁,锁的粒度越少越好。

看下面的例子:

    FruitCount fruitCount = new FruitCount();
FruitCount fruitCount_3 = new FruitCount();
//线程1、2 使用了同一个FruitCount对象(fruitCount )
Thread thread_1 = new Thread(new MyRunable(fruitCount));
Thread thread_2 = new Thread(new MyRunable(fruitCount));
//线程3使用了不同的FruitCount对象(fruitCount_3 )
Thread thread_3 = new Thread(new MyRunable(fruitCount_3));

   线程1、2将会互斥访问getAmount( )方法,线程3则独享getAmount( )方法;线程1、2的getAmount( )方法中的对象锁是fruitCount ,线程3的则是 fruitCount_3;这便是对象锁的粒度范围,不同的对象,锁是相互隔离的。而对于setData( )方法,三个线程都要互斥访问访问它,因为是同一个锁 -- FruitCount.class类锁。

class FruitCount{

   static int price = 5;
static int num = 10; public void setData(int price,int num){
//类锁,以FruitCount.class为锁
synchronized(FruitCount.class){
this.price = price;
this.num = num;
}
} public int getAmount(){
//对象锁,以当前对象为锁
synchronized (this) {
int amount = price*num;
return amount;
}
}
}
class MyRunable implements Runnable{

	FruitCount fruitCount;
public MyRunable(FruitCount fruitCount){
this.fruitCount = fruitCount;
} @Override
public void run() {
//setData方法 有类锁
fruitCount.setData(5, 10);
//getAmount方法 里面有对象锁,就是fruitCount对象
fruitCount.getAmount();
}
}

二、synchronized 用法

synchronized 的用法只有两种:修饰方法修饰代码块

1、在方法声明时使用,修饰方法

注意:这个synchronized 修饰符 不会参与方法签名的比较;

语法:

public synchronized void synMethod() {
//方法体
}

有以下两种情况:

  • 1.1、修饰的方法是普通的成员方法,那么是对象锁,便是以当前对象为锁,即调用这个方法的对象
  • 1.2、修饰的方法是静态方法,则是类锁。
public synchronized static int countData(int data){
return data*data;
}

2、修饰一个代码块

语法:

public int synMethod(int a1){
synchronized( object ) {
//代码块,一次只能有一个线程进入
}
}

有以下3种情况:

2.1、object 是 this,是对象锁,this指代当前对象

public int getAmount(){
//对象锁,以当前对象为锁
synchronized (this) {
int amount = price*num;
return amount;
}
}

2.2、object 是一个普通对象实例

  • 如果是静态对象,那么就是 类锁;
  • 如果是非静态对象:成员对象变量、局部变量(甚至可以是 方法参数),那么就是对象锁;
public void setObj(){
FruitCount fruitCount = null;
//局部变量
synchronized(fruitCount){
fruitCount = new FruitCount();
}
}

2.3、object 是一个类的class 对象,那么就是类锁

public void setData(int price,int num){
//类锁,以FruitCount.class为锁
synchronized(FruitCount.class){
this.price = price;
this.num = num;
}
}

小 结:

1、出现类锁的情况:

  • 以 类.class 为锁
  • 以 静态变量为锁
  • 修饰静态方法

2、出现对象锁的情况:

  • 以实例成员对象为锁(特殊:this 指当前对象)
  • 以局部变量(甚至是方法传进来的参数)为锁、
  • 修饰成员方法

3、当synchronized修饰方法时,synchronized是不参与 方法签名的比较;

内置锁(一)synchronized 介绍与用法的更多相关文章

  1. 深入理解Java内置锁和显式锁

    synchronized and Reentrantlock 多线程编程中,当代码需要同步时我们会用到锁.Java为我们提供了内置锁(synchronized)和显式锁(ReentrantLock)两 ...

  2. 七 内置锁 wait notify notifyall; 显示锁 ReentrantLock

    Object中对内置锁进行操作的一些方法: Java内置锁通过synchronized关键字使用,使用其修饰方法或者代码块,就能保证方法或者代码块以同步方式执行. 内置锁使用起来非常方便,不需要显式的 ...

  3. Java 并发:内置锁 Synchronized

    摘要: 在多线程编程中,线程安全问题是一个最为关键的问题,其核心概念就在于正确性,即当多个线程訪问某一共享.可变数据时,始终都不会导致数据破坏以及其它不该出现的结果. 而全部的并发模式在解决问题时,採 ...

  4. 深入理解java内置锁(synchronized)和显式锁(ReentrantLock)

    多线程编程中,当代码需要同步时我们会用到锁.Java为我们提供了内置锁(synchronized)和显式锁(ReentrantLock)两种同步方式.显式锁是JDK1.5引入的,这两种锁有什么异同呢? ...

  5. synchronized内置锁

    synchronized内置锁,如果发生阻塞,无法被中断,除非关闭jvm.因此不能从死锁中恢复.

  6. java synchronized内置锁的可重入性和分析总结

    最近在读<<Java并发编程实践>>,在第二章中线程安全中降到线程锁的重进入(Reentrancy) 当一个线程请求其它的线程已经占有的锁时,请求线程将被阻塞.然而内部锁是可重 ...

  7. Java内置锁synchronized的实现原理

    简述Java中每个对象都可以用来实现一个同步的锁,这些锁被称为内置锁(Intrinsic Lock)或监视器锁(Monitor Lock). 具体表现形式如下: 1.普通同步方法,锁的是当前实例对象 ...

  8. 内置锁(二)synchronized下的等待通知机制

    一.等待/通知机制的简介 线程之间的协作:   为了完成某个任务,线程之间需要进行协作,采取的方式:中断.互斥,以及互斥上面的线程的挂起.唤醒:如:生成者--消费者模式.或者某个动作完成,可以唤醒下一 ...

  9. jvm内置锁synchronized不能被中断

    很久没看技术书籍了,今天看了一下<七周七并发模型>前面两章讲的java,写的还是有深度的.看到了一个有demo,说jvm内置锁synchronized是不能被中断的.照着书上写了个demo ...

随机推荐

  1. Texas Instruments matrix-gui-2.0 hacking -- submenu.php

    <?php /* * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistrib ...

  2. DoTween可视化编程用法详解

    DoTween可视化编辑 本文提供全流程,中文翻译.Chinar坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分享.心创新 ...

  3. ubuntu 部署wordPress

    准备 LAMP 环境 1.安装 Apache2 sudo apt-get install apache2 -y 安装好后,您可以通过访问服务器IP地址 x.x.x.x 查看到 “it works” 界 ...

  4. PR

    3.1音频轨道与播放 单声道音轨: 立体声音轨:立体声音频文件 3.2 音频过渡 需要先把第一段视频的结尾与第二段视频的开头切除,然后在使用恒定功率. 3.3  调音台的简单使用 调节音频: 显示声音 ...

  5. UVA 156:Ananagrams (vector+map+sort)

    题意:一大堆单词中间有空格隔开,以'#'结束输出,问只出现一次的的单词有哪些(如果两个具有相同的长度,相同的字母也算是相同的,不区分大小写,如:noel和lone属于一个单词出现两次).最后按照字典序 ...

  6. .NET 中使用 Mutex 进行跨越进程边界的同步

    Mutex 是 Mutual Exclusion 的缩写,是互斥锁,用于防止两个线程同时对计算机上的同一个资源进行访问.不过相比于其他互斥的方式,Mutex 能够跨越线程边界. 本文内容 Mutex ...

  7. javascript : location 对象

    window.location: window的location对象 window.location.href 整个URl字符串(在浏览器中就是完整的地址栏) window.location.prot ...

  8. 进程间通信--POSIX消息队列

    相关函数: mqd_t mq_open(const char *name, int oflag); mqd_t mq_send(mqd_t mqdes, const char *msg_ptr, si ...

  9. 如何取出word文档里的图片

    在生活当中,Word办公是必不可少的.但是在工作中也会遇到一些麻烦,比如说如何取出word文档里的图片呢?有的人会通过复制粘贴,通过画图保存,可是这种方法未免太繁琐了吧.下面我就来分享一下我的经验. ...

  10. spring 核心思想:AOP 理解

    什么是AOP? AOP概念介绍 所谓AOP,即Aspect orientied program,就是面向方面(切面)的编程. 面向切面编程Aspect-Orlented-Programming,即AO ...