JUC之八种问题中锁的状态

96 阅读3分钟

8种问题锁状态:

「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战」。

该部分全部围绕的是以下内容并结合相应的例子

synchronized实现同步的基础:Java中每个对象都可以作为锁。

具体表现为以下三种形式:(之前只是简单的了解)

  1. 对于普通同步方法,锁是当前实例对象。
  2. 对于静态同步方法,锁是当前类的Class对象。
  3. 对于同步方法块,锁是Synchonized括号里配置的对象

当一个线程试图访问同步代码块时,它首先必须得到锁,退出或抛出异常时必须释放锁

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

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

具体的例子如下:

package com.JUC;
​
import java.util.concurrent.TimeUnit;
​
class phone{
    public static synchronized  void sendEmail() throws Exception {
//        Thread.sleep(4000);
        //暂定4s
        TimeUnit.SECONDS.sleep(1);
        System.out.println("sendEmail-------");
    }
    public synchronized void sendMessage() throws Exception {
        System.out.println("sendSMS----------");
    }
    public void hello(){
        System.out.println("hello wold");
    }
}
​
public class lockPhenomenon {
    public static void main(String[] args) throws InterruptedException {
        //phone 是模板--class,new phone --this
        phone phone = new phone();
        phone phone2 = new phone();
        new Thread(()->{
            try {
                phone.sendEmail();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"AAA").start();
        Thread.sleep(100);
        new Thread(()->{
            try {
//                phone.sendMessage();
                //phone.hello();
                phone2.sendMessage();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"BBB").start();
    }
}
  • 多线程8锁问题描述
    1. 标准访问,先打印邮件还是短信
  • sendEmail-------
  • sendSMS----------
  • 2、邮件方法暂停4s,请问先打印邮件还是短信
  • sendEmail-------
  • sendSMS----------

解释1-2问题:synchronized锁的是当前类对象,一个对象里面如果有多个synchronized方法,在某个时刻内,只要一个线程去调用其中的一个synch方法了,其他线程都得只能等待,换句话说,某一个时刻内,只能有唯一一个线程去访问这些synchronized方法,锁的是当前对象this,被锁定后,其他的线程都不能进入到当前对象的其他synchronized方法。

  • 3、新增一个普通方法hello,先打印邮件还是hello.
  • hello wold
  • sendEmail------- 解释: 加个普通方法后发现和同步锁无关,
  • 4、两部手机,先打印邮件还是先打印短信。
  • sendSMS----------
  • sendEmail------- 解释4: 换成两个对象后,不是同一把锁了,情况立刻变化
  • 5、两个静态同步方法,同一部手机,请问先打印邮件还是短信
  • sendEmail-------
  • sendSMS----------
  • 6、两个静态同步方法,两部手机,请问先打印邮件还是短信
  • sendEmail-------
  • sendSMS----------

解释5-6问题: 都换成静态同步方法后,情况又发生了变化,synchronized锁的是new--this,具体的对象(如一部部手机) static synchronized锁的是 静态 class---模板

明白上述的问题和答案,问题7.8自然也就会了

  • 7、一个普通同步方法,一个静态同步方法,1部手机,请问先打印邮件还是短信
  • sendSMS----------
  • sendEmail-------
  • 8、一个普通同步方法,一个静态同步方法,2部手机,请问先打印邮件还是短信
  • sendSMS----------
  • sendEmail-------