Synchronized的三种写法

文章目录

  • 前言
  • 一、synchronized是什么
  • 二、synchronized的三种写法
    • 1、同步代码块
    • 2、在实例方法上使用synchronized
    • 3、在静态方法上使用synchronized
  • 总结





前言

总结一下自己在学习Synchronized 以及它的三种写法。

一、synchronized是什么?

synchronized是由JVM实现的一种互斥同步的一种方式,被synchronized修饰过的程序块在编译前后被编译器生成了monitorenter和monitorexit两个字节码指令。

如果这个方法使用了synchronized的时候,代表它加上了锁,运行此方法的时都要检查它有没有被其他线程正在使用(或者该类的其他同步方法),有的话要等它使用完,没有的话则直接锁定调用者,然后直接运行。它包括两种用法:synchronized方法和synchronized块。



二、synchronized的三种写法




1、同步代码块

代码如下(示例):

package com.demo;

public class Demo {
    public static void main(String[] args) throws InterruptedException {
        MyClass mc=new MyClass();
        
        Thread t1=new MyThread(mc);
        Thread t2=new MyThread(mc);
        
        t1.setName("t1");
        t2.setName("t2");
        
        t1.start();
        Thread.sleep(1000);//这个睡眠的作用 是为了保证t1线程先执行。
        t2.start();
    }

}

class MyThread extends Thread {
    private MyClass mc;
    
    public MyThread (MyClass mc) {
        this.mc = mc;
    }
    
    public void run(){
        if(Thread.currentThread().getName().equals("t1")) {
            mc.doSome();
        }
        if(Thread.currentThread().getName().equals("t2")) {
            mc.doOther();
        }
    }
    
}

class MyClass{
    //synchronized出现再类方法上,表示锁this。
    public synchronized void doSome(){
        System.out.println("doSome 执行开始");
        try {
            Thread .sleep(1000*5);//睡眠五秒
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("doSome 执行结束");
    }
    
    public void doOther() {
        System.out.println("doOther 执行开始");
        System.out.println("doOther 执行结束");
    }
}
doOther方法执行的时候不需要等待被修饰过的doSome方法结束,因为doOther方法没有被synchronized修饰,所以它不用排队等待。 

2、在实例方法上使用synchronized

代码如下(示例):

package com.demo;

public class Demo {
    public static void main(String[] args) throws InterruptedException {
        MyClass mc=new MyClass();
        
        Thread t1=new MyThread(mc);
        Thread t2=new MyThread(mc);
        
        t1.setName("t1");
        t2.setName("t2");
        
        t1.start();
        Thread.sleep(1000);//这个睡眠的作用 是为了保证t1线程先执行。
        t2.start();
    }

}

class MyThread extends Thread {
    private MyClass mc;
    
    public MyThread (MyClass mc) {
        this.mc = mc;
    }
    
    public void run(){
        if(Thread.currentThread().getName().equals("t1")) {
            mc.doSome();
        }
        if(Thread.currentThread().getName().equals("t2")) {
            mc.doOther();
        }
    }
    
}

class MyClass{
    //synchronized出现再类方法上,表示锁this。
    public synchronized void doSome(){
        System.out.println("doSome 执行开始");
        try {
            Thread .sleep(1000*5);//睡眠五秒
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("doSome 执行结束");
    }
    
    public synchronized void doOther() {
        System.out.println("doOther 执行开始");
        System.out.println("doOther 执行结束");
    }
}
在两个方法前都加上synchronized修饰,doOther方法执行的时候需要等待doSome方法结束完之后才执行doSome,因为锁被doSome占了,所以要排队等待。 
我们再开启一个线程:package com.demo;

public class Demo {
    public static void main(String[] args) throws InterruptedException {
        //开启两个线程
        MyClass mc1=new MyClass();
        MyClass mc2=new MyClass();
        
        Thread t1=new MyThread(mc1);
        Thread t2=new MyThread(mc2);
        
        t1.setName("t1");
        t2.setName("t2");
        
        t1.start();
        Thread.sleep(1000);//这个睡眠的作用 是为了保证t1线程先执行。
        t2.start();
    }

}

class MyThread extends Thread {
    private MyClass mc;
    
    public MyThread (MyClass mc) {
        this.mc = mc;
    }
    
    public void run(){
        if(Thread.currentThread().getName().equals("t1")) {
            mc.doSome();
        }
        if(Thread.currentThread().getName().equals("t2")) {
            mc.doOther();
        }
    }
    
}

class MyClass{
    //synchronized出现再类方法上,表示锁this。
    public synchronized void doSome(){
        System.out.println("doSome 执行开始");
        try {
            Thread .sleep(1000*5);//睡眠5秒
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("doSome 执行结束");
    }
    
    public synchronized void doOther() {
        System.out.println("doOther 执行开始");
        System.out.println("doOther 执行结束");
    }
}doOther方法执行的时候不需要等待doSome方法结束,因为MyClass对象是两个,两把锁,互不干涉。 

3、在静态方法上使用synchronized

package com.demo;


public class Demo {
    public static void main(String[] args) throws InterruptedException {
        //开启两个线程
        MyClass mc1=new MyClass();
        MyClass mc2=new MyClass();
        
        Thread t1=new MyThread(mc1);
        Thread t2=new MyThread(mc2);
        
        t1.setName("t1");
        t2.setName("t2");
        
        t1.start();
        Thread.sleep(1000);//这个睡眠的作用 是为了保证t1线程先执行。
        t2.start();
    }

}

class MyThread extends Thread {
    private MyClass mc;
    
    public MyThread (MyClass mc) {
        this.mc = mc;
    }
    
    public void run(){
        if(Thread.currentThread().getName().equals("t1")) {
            mc.doSome();
        }
        if(Thread.currentThread().getName().equals("t2")) {
            mc.doOther();
        }
    }
    
}

class MyClass{
    //synchronized出现再类方法上,表示锁this。
    public synchronized static void doSome(){
        System.out.println("doSome 执行开始");
        try {
            Thread .sleep(1000*5);//睡眠5秒
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("doSome 执行结束");
    }
    
    public synchronized static void doOther() {
        System.out.println("doOther 执行开始");
        System.out.println("doOther 执行结束");
    }
}

doOther方法执行的时候不需要等待doSome方法结束,因为静态方法是类锁,不管创建了几个对象,类锁只有一把。





总结

对象锁:1个对象1把锁,100个对象有100把锁。

类锁:100个对象,全部都是这一把锁。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
synchronized关键字可以保证并发编程的三大特性:原子性、可见性和有序性。 原子性是指一个操作不可中断,要么全部执行成功,要么全部不执行。synchronized关键字可以保证被它修饰的代码或者方法在同一时刻只能被一个线程执行,从而保证了原子性。可见性是指当一个线程修改了共享变量的值,其他线程能够立即看到这个修改后的值。synchronized关键字可以保证共享变量的修改对其他线程是可见的。有序性是指程序执行的顺序必须按照代码的顺序来执行。synchronized关键字可以保证在同一时刻只有一个线程执行被它修饰的代码或者方法,从而保证了代码的有序性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Java 基础 —— synchronized 关键字详解](https://blog.csdn.net/IT__learning/article/details/121115655)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [彻底理解synchronized(一)](https://blog.csdn.net/qq_15127715/article/details/117913794)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值