zoukankan      html  css  js  c++  java
  • 线程八锁

    线程八锁

    一、多线程中关于上锁

      一个对象里面如果有多个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】。

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

  • 相关阅读:
    RECOVER DATABASE SKIP TABLESPACE
    mysql加解密函数
    node获取代码的svn版本号,并打包的时候,输出指定文件到打包后的项目里面
    layer.open iframe自动高度
    IIS部署.net5项目
    使用Windows命令行启动关闭服务(net,sc用法)(转)
    centos7 修改IP 设置静态IP,开启SSH
    链接PostgreSQL报错authentication method 10 not supported解决
    PostgreSQL Windows安装教程
    POI隐藏行 隐藏列,EasyExcel隐藏行 EasyExcel隐藏列
  • 原文地址:https://www.cnblogs.com/albertrui/p/8406222.html
Copyright © 2011-2022 走看看