synchronized关键字

本文详细解析了Java中synchronized关键字的使用方式及特性,包括其作用于实例方法、静态方法和代码块的不同表现,以及锁的重入性和如何处理异常情况下的锁释放。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

synchronized关键字的使用:

public synchronized void test(){}加在方法上,这时表示锁定的是当前对象
public synchronized static void test(){}加在静态方法上,这时锁定的是整个类
sychronized(object){}synchronized代码块,锁定的是object对象

一个对象里面加锁的方法和不加锁的方法可以同步执行
加锁方法执行时,不加锁的方法不受影响写方法执行时如果进行读操作,而且读操作没有加锁的话就会产生脏读(dirtyRead)copyOnWrite

public class Test2 {
    private String name;
    private double balance;
    //一个对象里面加锁的方法和不加锁的方法可以同步执行,加锁方法执行时,不加锁的方法不受影响
    public synchronized void set(String name , Double blance){
        this.name=name;
        try{
            Thread.sleep(2000);
        }catch (Exception e){
            e.printStackTrace();
        }
        this.balance=blance;
    }
    public double get(){
        return this.balance;
    }
    //写方法执行时如果进行读操作,而且读操作没有加锁的话就会产生脏读(dirtyRead) copyOnWrite
    public static void main(String args[]){
        Test2 t=new Test2();
        new Thread(()->t.set("zhangsan",100.0)).start();
        try{
            TimeUnit.SECONDS.sleep(1);
        }catch (Exception e){
            e.printStackTrace();
        }

        System.out.println(t.get());

        try{
            TimeUnit.SECONDS.sleep(2);
        }catch (Exception e){
            e.printStackTrace();
        }

        System.out.println(t.get());
    }
}

运行结果Test2运行结果
set方法加了synchronized关键字,是同步方法,get方法不是同步方法。从程序中可以看出在执行set方法时,同时执行了get方法打印出了为赋值前的balance。之后再执行get方法拿到了赋值之后的值

synchronized锁是可以重入的
一个对象有两个synchronized修饰的方法,当一个线程拿到这个对象的锁执行其中一个方法时,可以再次获得这个对象的锁,即在此方法中调用另外一个同步方法
//一个同步方法可以调用另外一个同步方法,一个线程已经拥有该对象的锁,再次申请时任然会获得该对象的锁
//也就是说synchronized的锁是可以重入的

public class Test3 {
    synchronized void m1(){
        System.out.println("m1");
        try{
            TimeUnit.SECONDS.sleep(1);
        }catch (Exception e){
            e.printStackTrace();
        }
        m2();
        System.out.println(2);
    }
    synchronized void m2(){
        try{
            TimeUnit.SECONDS.sleep(2);
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println("m2");
    }

    public static void main(String args[]){
        Test3 t=new Test3();
        t.m1();
    }
}

Test3运行结果
m1()、m2()都是同步方法,m1()中调用了m2()方法。执行m1()时线程已经获得了t这把锁,再调用m2()方法,需要再次获得t这把锁,程序执行成功了。说明synchronized是可以重入的。

synchronized代码块里面产生异常时,程序默认会释放锁
如果产生异常时也不想释放锁,可以用try catch代码块抓住异常

public class Test6 {
    int count=0;
    public synchronized void m(){
        while (true){
            count++;
            System.out.println(Thread.currentThread().getName()+" : "+count);
            try{
                TimeUnit.SECONDS.sleep(1);
            }catch (Exception e){
                e.printStackTrace();
            }
            //int i=1/0;//此处抛出异常,锁将被释放,要想不被释放,可以在这里进行catch,然后继续循环

            try{
                if(count==5){
                    int i=1/0;//此处抛出异常,锁将被释放,要想不被释放,可以在这里进行catch,然后继续循环
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    public static void main(String args[]){
        Test6 t=new Test6();
        new Thread(()->t.m(),"t1").start();

        try {
            TimeUnit.SECONDS.sleep(2);
        }catch (Exception e){
            e.printStackTrace();
        }

        new Thread(()->t.m(),"t2").start();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值