synchronized关键字

一、使用

1、几种使用场景

(1)在静态方法中:静态同步方法
(2)在实例方法中:实例同步方法
(3)同步代码块

2、代码演示

//演示synchronized关键字
public class SynchronizedDemo {
    //1、静态方法:静态同步方法
    public static synchronized void test1(){

    }
    //同tset1()
    public static void test1_2(){
        synchronized (SynchronizedDemo.class){

        }
    }
    //2、实例方法:实例同步方法
    public synchronized void test2(){

    }
    //同test2()
    public synchronized void test2_2(){
        synchronized (this){

        }
    }


    public static void main(String[] args) {
        Object o = new Object();
        //3、同步代码块
        synchronized (o){

        }
    }
}

二、相关解释

1、synchronized的底层是使用操作系统的mutex lock实现的。

当线程释放锁时,JMM会把该线程对应的工作内存中的共享变量刷新到主内存中
当线程获取锁时,JMM会把该线程对应的本地内存置为无效。从而使得被监视器保护的临界区代码必须从主内存中读取共享变量
synchronized用的锁是存在Java对象头里的

2、对象锁:每个对象都有对象头,包含锁

3、synchronized是获取对象锁的操作

(1)申请对象锁成功
		1)持有对象锁,进入代码块
		2)执行代码
	    3)退出代码块,归还对象锁
			 --- JVM会将竞争失败的线程唤醒
			 --- 唤醒的线程重新竞争
 			 --- 循环(1)和(2)的逻辑
(2)申请对象锁失败:线程进入下一个同步队列阻塞
		 1) JVM管理synchronized竞争失败
			 --- 由运行态转变成阻塞态的方式
			 --- 将线程放到一个同步队列的数据结构中
			 --- 对象锁再次可用,将所有竞争该对象锁失败的线程唤醒(阻塞转	变为被唤醒)

4、对象:普通Java对象,类对象

5、注意事项

(1)只有多个线程同一个对象申请对象锁时,才会有同步互斥现象

(2)同步互斥:同步代码块,在一个时间点,只有一个线程运行

(3)多个线程竞争不同对象的对象锁时,不会有同步互斥现象

6、静态同步方法 、实例同步方法都可以转换为同步代码块

三、示例

对于以下代码,每两个方法在不同线程中运行时是否会出现同步互斥现象

public class SynchronizedTest {
    private Object o = new Object();
    private static Object T =SynchronizedDemo.class;
    public static synchronized void test1() throws InterruptedException {
        Thread.sleep(99999999);
    }
    public synchronized void test2() throws InterruptedException {
        Thread.sleep(99999999);
    }
    public void test3() throws InterruptedException {
        synchronized (o){
            Thread.sleep(99999999);
        }
    }
    public void test4() throws InterruptedException {
        synchronized (T){
            Thread.sleep(99999999);
        }
    }
}

在这里插入图片描述
1、红色格子,由于多个线程使用的都是同一个对象,所以会出现同步互斥现象

2、绿色格子,由于多个线程使用的对象不同,所以不会出现同步互斥现象

3、黄色格子的情况需要根据this对象是否是同一个进行判断

对于test2和test2:

(1)情况一:this对象不是同一个,不会出现同步互斥

  //情况1,不会同步互斥
    new Thread(() -> {
        try {
            new SynchronizedTest().test2();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }).start();
    new Thread(() -> {
        try {
            new SynchronizedTest().test2();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }).start();
     

(2)情况二:this对象是同一个,会出现同步互斥

//情况2,会同步互斥
SynchronizedDemo t =new SynchronizedDemo();
new Thread(() -> {
    t.test2();
 }).start();
new Thread(() -> {
    t.test2();
}).start();

test3和test3同上

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值