• 线程八锁


    线程八锁

    一、多线程中关于上锁

      一个对象里面如果有多个synchronized方法,某一个时刻内,只要一个线程去调用其中的一个synchronized方法了,其它的线程都只能等待,换句话说,某一个时刻内,只能有唯一一个线程去访问这些synchronized方法

      锁的是当前对象this,被锁定后,其它的线程都不能进入到当前对象的其它的synchronized方法

      加个普通方法后发现和同步锁无关

      换成两个对象后,不是同一把锁了,情况立刻变化。

      都换成静态同步方法后,情况又变化

      所有的非静态同步方法用的都是同一把锁——实例对象本身,也就是说如果一个实例对象的非静态同步方法获取锁后,该实例对象的其他非静态同步方法必须等待获取锁的方法释放锁后才能获取锁,可是别的实例对象的非静态同步方法因为跟该实例对象的非静态同步方法用的是不同的锁,所以毋须等待该实例对象已获取锁的非静态同步方法释放锁就可以获取他们自己的锁。

      所有的静态同步方法用的也是同一把锁——类对象本身,这两把锁是两个不同的对象,所以静态同步方法与非静态同步方法之间是不会有竞态条件的。但是一旦一个静态同步方法获取锁后,其他的静态同步方法都必须等待该方法释放锁后才能获取锁,而不管是同一个实例对象的静态同步方法之间,还是不同的实例对象的静态同步方法之间,只要它们同一个类的实例对象!

    二、代码示例

     1 package me.concurrent.t8m;
     2 
     3 /**
     4  * 判断打印的 "one" or "two" ?
     5  * 
     6  * 1. 两个普通同步方法,两个线程,标准打印, 打印? //one two 
     7  * 2. 新增 Thread.sleep() 给 getOne() ,打印?//one two 
     8  * 3. 新增普通方法 getThree() , 打印? //three one two 
     9  * 4. 两个普通同步方法,两个 Number对象,打印? //two one 
    10  * 5. 修改 getOne() 为静态同步方法,打印? //two one 
    11  * 6. 修改两个方法均为静态同步方法,一个Number 对象? //one two 
    12  * 7. 一个静态同步方法,一个非静态同步方法,两个 Number 对象? //two one 
    13  * 8. 两个静态同步方法,两个 Number 对象? //one two
    14  * 
    15  * 线程八锁的关键: 
    16  * ①非静态方法的锁默认为 this, 静态方法的锁为 对应的 Class 实例 
    17  * ②某一个时刻内,只能有一个线程持有锁,无论几个方法。
    18  */
    19 public class TestThread8Monitor {
    20 
    21     public static void main(String[] args) {
    22     Number number = new Number();
    23     Number number2 = new Number();
    24 
    25     new Thread(new Runnable() {
    26         @Override
    27         public void run() {
    28         number.getOne();
    29         }
    30     }).start();
    31 
    32     new Thread(new Runnable() {
    33         @Override
    34         public void run() {
    35         //number.getTwo();
    36         number2.getTwo();
    37         }
    38     }).start();
    39 
    40     /*
    41      * new Thread(new Runnable() {
    42      *     @Override 
    43      *     public void run() { 
    44      *         number.getThree(); 
    45      *     } 
    46      * }).start();
    47      */
    48 
    49     }
    50 
    51 }
    52 
    53 class Number {
    54 
    55     public static synchronized void getOne() {// Number.class
    56     try {
    57         Thread.sleep(3000);
    58     } catch (InterruptedException e) {
    59     }
    60     System.out.println("one");
    61     }
    62 
    63     public synchronized void getTwo() {// this
    64     System.out.println("two");
    65     }
    66 
    67     public void getThree() {
    68     System.out.println("three");
    69     }
    70 
    71 }
    View Code

      如上代码:判断打印的 "one" or "two" ?

      ①两个普通同步方法,两个线程,标准打印, 打印? //one two

      ②新增 Thread.sleep() 给 getOne() ,打印?//one two

      ③新增普通方法 getThree() , 打印? //three one two

      ④两个普通同步方法,两个 Number对象,打印? //two one

      ⑤修改 getOne() 为静态同步方法,打印? //two one

      ⑥修改两个方法均为静态同步方法,一个Number 对象? //one two

      ⑦一个静态同步方法,一个非静态同步方法,两个 Number 对象? //two one

      ⑧两个静态同步方法,两个 Number 对象? //one two

      线程八锁的关键:

      ①非静态方法的锁默认为 this, 静态方法的锁为 对应的 Class 实例

      ②某一个时刻内,只能有一个线程持有锁,无论几个方法。

    如果,您对我的这篇博文有什么疑问,欢迎评论区留言,大家互相讨论学习。
    如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】。
    如果,您希望更容易地发现我的新博客,不妨点击一下左下角的【关注我】。
    如果,您对我的博文感兴趣,可以关注我的后续博客,我是【AlbertRui】。

    转载请注明出处和链接地址,欢迎转载,谢谢!

  • 相关阅读:
    rsync+crontab 企业实战 全量备份
    添加共享文件盘,切换用户访问共享
    一天电你千百回,这样做远离静电你造么~
    Network Password Recovery工具查看windows凭据密码
    su 和su
    运维面试 怎么实现程序自启
    在tomcat中配置域名的方法
    使用windows update blocker工具关闭windows系统自动更新
    CVM 母机透传,什么是透传模块?为什么要透传?
    硬盘接口类型
  • 原文地址:https://www.cnblogs.com/albertrui/p/8406222.html
Copyright © 2020-2023  润新知