synchronized关键字详解(二)

synchronized关键字的性质

1.可重入:同一线程的外层函数获得锁之后,内层函数可直接再次获得该锁,好处:避免死锁,提升封装性

证明可重入粒度:1、同一个方法是可重入的

        2、可重入不要求是同一个方法

        3、可重入不要求是同一个类

可重入原理:加锁次数计数器

      • JVM负责跟踪对象被加锁的次数;
      • 线程第一次给对象加锁的时候计数变为1,每当这个相同的线程在这个对象上加锁时,计数递增;
      • 每当任务离开时,计数会减1,计数为0时,锁被完全释放。

2.不可中断:如果一个线程拿到一把锁,另一个线程要想获得这把锁,只能等待或者阻塞,直到别的线程释放这个锁,如果另一个线程一直不释放,那就只能一直等待下去。(相比之下,Lock类拥有中断的能力:1.lock如果等的时间太长,有权利中断当前获得锁的这个线程;2.lock等待时间太长不想等,可以自动退出)

同一个方法是可重入的:

递归调用method方法打印出a=1;就说明进入该方法两次

/**
 *
 * 验证synchronized的可重入性质1:
 * 同一个方法是可重入的
 * @author Administrator
 *
 */
public class SynchronizeTest04 implements Runnable{
    static SynchronizeTest04 instance1 = new SynchronizeTest04();
    int a = 0;
    @Override
    public void run() {
        //调用加synchronized关键字的普通方法
        method();
    }
    public synchronized void method() {
        System.out.println("a="+a);
        if(a==0) {
            a++;
            method();
        }
    }
    public static void main(String[] args) {
        Thread t1 = new Thread(instance1,"线程一");
        t1.start();
        while(t1.isAlive()) {

        }
        System.out.println("执行结束");
    }
}
 

可重入不要求是同一个方法:

run方法中调用被synchronized修饰的method1方法,在method1中调用被synchronized修饰的method2方法

/**
 *
 * 验证synchronized的可重入性质2:
 * 可重入不要求是同一个方法
 * @author Administrator
 *
 */
public class SynchronizeTest04 implements Runnable{
    static SynchronizeTest04 instance1 = new SynchronizeTest04();
    int a = 0;
    @Override
    public void run() {
        //调用加synchronized关键字的普通方法
        method1();
    }
    public synchronized void method1() {
        System.out.println("我是方法一");
        method2();
    }
    public synchronized void method2() {
        System.out.println("我是方法二");
    }
    public static void main(String[] args) {
        Thread t1 = new Thread(instance1,"线程一");
        t1.start();
        while(t1.isAlive()) {

        }
        System.out.println("执行结束");
    }
}

可重入不要求是同一个方法

可重入不要求是同一个类:

由于main方法就是一个线程,所以这里用main方法演示,父类中创建被synchronized修饰的doSomething方法,子类中重写doSomething方法,并调用父类方法

/**
 *
 * 验证synchronized的可重入性质3:
 * 可重入不要求是同一个类
 * @author Administrator
 *
 */
public class SynchronizeTest05 {
    public synchronized void doSomething() {
        System.out.println("我是父类");
    }
    public static void main(String[] args) {
        Test t = new Test();
        t.doSomething();
    }
}
class Test extends SynchronizeTest05{
    //重写父类的方法,并调用父类方法
    public synchronized void doSomething() {
        System.out.println("我是子类");
        super.doSomething();
    }
}

可重入不要求是同一个类

synchronized关键字的缺点:

1、效率低:锁的释放少,试图获得锁时不能设置超时,不能中断一个正在获得锁的线程;

2、不够灵活:加锁和释放的时机单一,每个锁仅有单一的条件

3、无法知道是否成功获取到锁

在使用synchronized关键字时注意:锁对象不能为空、锁的作用域不宜过大、避免死锁。

原文地址:https://www.cnblogs.com/YpfBolg/p/10805794.html

时间: 2024-10-01 04:21:57

synchronized关键字详解(二)的相关文章

Java 多线程(六) synchronized关键字详解

Java 多线程(六) synchronized关键字详解 多线程的同步机制对资源进行加锁,使得在同一个时间,只有一个线程可以进行操作,同步用以解决多个线程同时访问时可能出现的问题. 同步机制可以使用synchronized关键字实现. 当synchronized关键字修饰一个方法的时候,该方法叫做同步方法. 当synchronized方法执行完或发生异常时,会自动释放锁. 下面通过一个例子来对synchronized关键字的用法进行解析. 1.是否使用synchronized关键字的不同 例子

Java synchronized 关键字详解

Java synchronized 关键字详解 前置技能点 进程和线程的概念 线程创建方式 线程的状态状态转换 线程安全的概念 synchronized 关键字的几种用法 修饰非静态成员方法 synchronized public void sync(){ } 修饰静态成员方法 synchronized public static void sync(){ } 类锁代码块 synchronized (类.class){ } 对象锁代码块 synchronized (this|对象){ } syn

synchronized关键字详解

1.    把synchronized当作函数修饰符时,示例代码如下:public synchronized void method(){//-.}这也就是同步方法,那这时synchronized锁定的是哪个对象呢?他锁定的是调用这个同步方法对象.也就是说,当一个对象P1在不同的线程中执行这个同步方法时,他们之间会出现阻塞,达到同步的效果.但是这个对象所属的Class所产生的另一对象P2却能够任意调用这个被加了synchronized关键字的方法. 2.同步块,示例代码如下:public voi

[java] java synchronized 关键字详解

Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码.当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一个时间内只能有一个线程得到执行.另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块.然而,当一个线程访问object的一个加锁代码块时,另一个线程仍然可以访问该object中的非加锁代码块. 一.synchronized同步方法 1.synchronized 同步方法,为对象锁 publ

SQL Server 一些关键字详解(二)

1.LEFT JOIN 容易让人误解的地方 背景:因为在网上搜了下 LEFT JOIN 和 OUTER APPLY 的区别,时发现,有的网友解释为: 1) A   left  join  B  的连接的记录数与A表的记录数同. 2) LEFT JOIN 左连接 -- 显示左表所有存在的记录 记录数=左表. 像这些说法都不对的.根据我测试得出的结论应该是: LEFT JOIN 返回结果数 >= 左表的记录数 网上有部分人的解释都漏了 大于(>) 的那部分,后我找了下感觉比较权威的答案: 在W3S

java关键字详解

Java关键字及其作用 目录 Java关键字及其作用--- 1 一.     关键字总览:2 二.     详细解释--- 3 1.访问控制--- 3 1)私有的-- 3      private 2)受保护的-- 3      protected 3)公共的-- 3      public 2.类.方法和变量修饰符--- 3 1)声明抽象-- 3      abstract 2)类-- 4      class 3)继承.扩展-- 4      extends 4)最终.不可改变-- 4   

lock与synchronized区别详解

1.线程与进程: 在开始之前先把进程与线程进行区分一下,一个程序最少需要一个进程,而一个进程最少需要一个线程. 线程是程序执行流的最小单位,而进程是系统进行资源分配和调度的一个独立单位. 2.Thread的几个重要方法: 我们先了解一下Thread的几个重要方法. a.start()方法,开始执行该线程:b.stop()方法,强制结束该线程执行:c.join方法,等待该线程结束.d.sleep()方法,线程进入等待.e.run()方法,直接执行线程的run()方法,但是线程调用start()方法

Delphi 关键字详解

absolute//它使得你能够创建一个新变量, 并且该变量的起始地址与另一个变量相同. var   Str: string[32];   StrLen: Byte absolute Str; //这个声明指定了变量StrLen起始地址与Str相同. //由于字符串的第0个位置保存了字符串的长度, 所以StrLen的值即字符串长度. begin   Str := 'abc';   Edit1.Text := IntToStr(StrLen); end; abstract//它允许你创建抽象的方法

“全栈2019”Java异常第九章:throws关键字详解

难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java异常第九章:throws关键字详解 下一章 "全栈2019"Java异常第十章:throw与throws区别详解 学习小组 加入同步学习小组,共同交流与进步. 方式一:关注头条号Gorhaf,私信"Java学习小组". 方式二:关注公众号Gorhaf,回复"Ja