Java synchronized解析

本文详细解析了synchronized关键字在Java中的使用方式及其实现机制,包括其如何保证多线程环境下的可见性、原子性和有序性。通过具体示例,阐述了普通方法、静态方法以及方法块的加锁原理。

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

多线程三大特性:

可见性、原子性、有序性

synchronize的特性:

1、同一时刻只有一个线程访问临界资源

2、其它未获取到锁执行权的线程必须排队等待

3、保证共享资源的原子性、可见性和有序性

4、进入synchronized范围内自动加锁,synchronized作用域外锁自动消除,即使异常也会释放锁

 synchronize加锁的方式:

  • 对于普通同步方法,锁是当前实例对象。

  • 对于静态同步方法,锁是当前类的Class对象。

  • 对于同步方法块,锁是Synchonized括号里配置的对象。

 

通过具体的例子来看一下

首先是普通方法:

 class NoSyncTest {
        public void method1() {
            Log.i("sync", "method 1 start");
            try {
                Log.i("sync", "method 1 execute");
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            Log.i("sync", "method 1 end");
        }

        public void method2() {
            Log.i("sync", "method 2 start");
            try {
                Log.i("sync", "method 2 execute");
                Thread.sleep(500);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            Log.i("sync", "method 2 end");
        }
    }

    private void noSyncTest() {
        final NoSyncTest test = new NoSyncTest();

        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                test.method1();
            }
        });

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                test.method2();
            }
        });

        thread1.start();
        thread2.start();
    }

这是一个没有任何同步的方法,NoSyncTest这个类有两个方法method1和method2,分别执行睡3s和0.5s的动作,然后再两个线程中分别调用这个类的实例test的两个方法,看一下结果:

 

可以看到method2和method1同时执行,method2因为sleep的时间短所以先结束。

再看一下普通方法同步:

class MethodSyncTest {
        public synchronized void method1() {
            Log.i("sync", "method 1 start");
            try {
                Log.i("sync", "method 1 execute");
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            Log.i("sync", "method 1 end");
        }

        public synchronized void method2() {
            Log.i("sync", "method 2 start");
            try {
                Log.i("sync", "method 2 execute");
                Thread.sleep(500);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            Log.i("sync", "method 2 end");
        }
    }

    private void MethodSyncTest() {
        final MethodSyncTest test = new MethodSyncTest();

        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                test.method1();
            }
        });

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                test.method2();
            }
        });

        thread1.start();
        thread2.start();
    

synchronize修饰的method1和method2,其他不变,看一下结果:

method1先执行然后3s之后结束了method2才开始执行。(注意这个地方不能new 不同的对象来调用方法,因为修饰普通方法本质是对对象的同步加锁。

看一下第三种静态同步方法:

 static class StaticMethodSyncTest {
        public static synchronized void method1() {
            Log.i("sync", "method 1 start");
            try {
                Log.i("sync", "method 1 execute");
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            Log.i("sync", "method 1 end");
        }

        public static synchronized void method2() {
            Log.i("sync", "method 2 start");
            try {
                Log.i("sync", "method 2 execute");
                Thread.sleep(500);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            Log.i("sync", "method 2 end");
        }
        public static synchronized void method3() {
            Log.i("sync", "method 3 start");
            try {
                Log.i("sync", "method 3 execute");
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            Log.i("sync", "method 3 end");
        }
    }

    private void StaticMethodSyncTest() {
        final StaticMethodSyncTest test1 = new StaticMethodSyncTest();
        final StaticMethodSyncTest test2 = new StaticMethodSyncTest();

        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                test1.method1();
            }
        });

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                test2.method2();
            }
        });
        Thread thread3 = new Thread(new Runnable() {
            @Override
            public void run() {
                StaticMethodSyncTest.method3();
            }
        });

        thread1.start();
        thread2.start();
        thread3.start();
    }

static修饰方法相当于这个方法是类方法,可以直接通过类名.方法名调用。我们在这new出了test1和test2两个对象分别调用method1和method2,以及通过类名.方法名调用method3,看一下结果

method1、method2、method3顺序执行。(同步静态方法的本质是锁的当前类

转载于:https://www.cnblogs.com/hxchaoshuai/p/9803160.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值