synchronized三种使用方式

前言

在多线程并发编程中Synchronized一直是元老级角色,大家都知道synchronized是重量级锁,但是随着Java SE1.6对Synchronized进行了各种优化之后,有些情况下它并不那么重了,与lock相比性能相差并不是很大,还是比较建议同步的时候优先使用synchronized。

三种使用方式

  • 修饰实例方法,作用于当前实例加锁,进入同步代码前要获得当前实例的锁

  • 修饰静态方法,作用于当前类对象加锁,进入同步代码前要获得当前类对象的锁

  • 修饰代码块,指定加锁对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁,同步代码块主要有三种方式 :synchronized(this)、synchronized (obj)、synchronized(Object.class),这三种方式分别是指同步本对象、同步其它对象、同步某个类。

  • 修饰非静态实列方法

public class SynchronizedDemo {

    public static void main(String[] args) {
        SynchronizedDemo demo1 = new SynchronizedDemo();
        // 修饰对象实列方法 锁定的当前实列对象 必须是公用同一个对象才行
        new Thread("thread1"){

            @Override
            public void run(){
                try {
                    demo1.demo1();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
        new Thread("thread2"){

            @Override
            public void run(){
                try {
                    demo1.demo1();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();

    }

    /**
     * 修饰实列方法
     * @throws InterruptedException 
     */
    public synchronized void demo1() throws InterruptedException{
        System.out.println("当前访问的线程名称是===="+Thread.currentThread().getName());
        //休眠2s 造成两个线程同时访问本实列方法
        Thread.sleep(2000);
    }
  • 修饰静态方法 同步的是方法所在的类对象
public class SynchronizedDemo {

    public static void main(String[] args) {
        /**
         * 修饰对象静态方法
         * 静态方法是类方法 静态方法即类方法,它属于一个类而不是某个对象
         * 在其上面加锁 锁的对象为类对象
         */
        new Thread("thread2-1"){

            @Override
            public void run(){
                try {
                    SynchronizedDemo.demo2();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
        new Thread("thread2-2"){

            @Override
            public void run(){
                try {
                    SynchronizedDemo.demo2();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();

    }


    /**
     *修饰静态方法 
     * @throws InterruptedException 
     */
    public synchronized static void demo2() throws InterruptedException{
        System.out.println("当前访问的线程名称是===="+Thread.currentThread().getName());
        Thread.sleep(2000);
    }
}
  • 修饰代码块 同步代码块主要有三种方式 :synchronized(this)、synchronized (obj)、synchronized(Object.class),这三种方式分别是指同步本对象、同步其它对象、同步某个类。
public class SynchronizedDemo {

    public static void main(String[] args) {
        /**
         * 修饰当前对象代码块
         * 锁的调用方法的当前对象
         * 代码块 this代表当前对象 
         * 3与1 2 不是同一个对象 13同时执行 12是同步执行
         */
        SynchronizedDemo block = new SynchronizedDemo();
        new Thread("thread1-1"){

            @Override
            public void run(){
                try {
                    new SynchronizedBlock(block).demo3();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
        new Thread("thread1-2"){

            @Override
            public void run(){
                try {
                    new SynchronizedBlock(new SynchronizedDemo()).demo3();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
        new Thread("thread1-3"){

            @Override
            public void run(){
                try {
                    new SynchronizedBlock(block).demo3();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();

        /**
         * 修饰对象实列方法-代码块-指定对象
         * 这里new了两个SynchronizedBlock对象 但由于指定同步对象是SynchronizedDemo
         * 所以方法依然会同步执行
         */
        SynchronizedDemo demo4 = new SynchronizedDemo();
        new Thread("thread4-1"){

            @Override
            public void run(){
                try {
                    new SynchronizedBlock(demo4).demo3_1();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
        new Thread("thread4-2"){

            @Override
            public void run(){
                try {
                    new SynchronizedBlock(demo4).demo3_1();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();

        /**
         * 修饰代码块-class
         * 这里new了两个SynchronizedDemo对象 但锁的是类对象
         * 所以方法依然会同步执行
         */
        new Thread("thread3-1"){

            @Override
            public void run(){
                try {
                    new SynchronizedBlock(new SynchronizedDemo()).demo3_2();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
        new Thread("thread3-2"){

            @Override
            public void run(){
                try {
                    new SynchronizedBlock(new SynchronizedDemo()).demo3_2();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }
}

class SynchronizedBlock {
    //声明一个实例变量
    private SynchronizedDemo demo;
    SynchronizedBlock(SynchronizedDemo demo){
         this. demo= demo;
    }
    /**
     * 同步当前对象
     * @throws InterruptedException
     */
    public void demo3() throws InterruptedException{
        synchronized(this){
            System.out.println("当前访问的线程名称是===="+Thread.currentThread().getName());
            Thread.sleep(2000);
        }
    }
    /**
     * 同步指定对象
     * @throws InterruptedException
     */
    public void demo3_1() throws InterruptedException{
        synchronized(demo){
            System.out.println("当前访问的线程名称是===="+Thread.currentThread().getName());
            Thread.sleep(2000);
        }
    }
    /**
     * 同步class类对象
     * @throws InterruptedException
     */
    public void demo3_2() throws InterruptedException{
        synchronized(SynchronizedDemo.class){
            System.out.println("当前访问的线程名称是===="+Thread.currentThread().getName());
            Thread.sleep(2000);
        }
    }
}

总结

  • 在多线程环境中,可以使用synchronized关键字对资源进行同步,synchronized关键字可以同步方法和代码块,同步的是对象或者类,而不是代码。
  • 一个对象中的同步方法一次只能被一个线程访问,如果有多个同步方法,一个线程一次也只能访问其中的一个同步方法,但是非同步方法不受任何影响。
  • 同步是通过加锁的形式来控制的,让一个线程访问一个同步方法时会获得这个对象的锁,只有退出同步方法时才会释放这个锁,其它线程才可访问
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值