线程八锁

线程八锁

一、多线程中关于上锁

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

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

 

posted on 2018-02-02 17:37  Ryan520  阅读(671)  评论(0编辑  收藏  举报

导航