synchronized关键字锁定的是对象不是代码块

总结

  1. synchronized关键字锁定的是对象不是代码块
  2. 锁定的对象有两种情况:
    ①类的实例
    锁定类的实例,不一定线程安全:
    锁定的对象是同一个,多线程访问是线程安全的
    锁定的对象不是同一个,多线程访问是线程不安全的
    ② 类的字节码(.class)
    锁定类的字节码,线程安全
public class Sync {
    public synchronized void test() {
        System.out.println("test start");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("test end");
    }
}

不同的对象

public class MyThread extends Thread{
    public void run() {
        Sync sync = new Sync();
        sync.test();
    }

    public static void main(String[] args) {
        for (int i = 0; i < 3; ++i) {
            Thread thread = new MyThread();
            thread.start();
        }
    }
}

执行结果
在这里插入图片描述
现象
在MyThread中,每次都new一个新的Sync对象,可以看到代码块test虽然被加了synchonized但是还是并行执行的,初步结论:锁住的不是代码块

同一个对象

public class MyThread2 extends Thread{
    public Sync sync;
    MyThread2(Sync sync) {
        this.sync = sync;
    }

    public void run() {
        System.out.println("hi....");
        sync.test();
    }

    public static void main(String[] args) {
        Sync sync = new Sync();
        for (int i = 0; i < 3; ++i) {
            Thread thread = new MyThread2(sync);
            thread.start();
        }
    }

执行结果
在这里插入图片描述
现象
可以看到当他们共用一个对象的时候,synchonized起了作用,这块代码是串行执行的

结论
锁住的是对象

如何在多对象的时候锁住代码?

解决也很简单,只要锁住同一个对象就行了。例如:synchronized后的括号中锁同一个固定对象,这样就行了。

这样是没问题,但是,比较多的做法是让synchronized锁这个类对应的Class对象。

public class Sync2 {
    public void test() {
        synchronized (Sync2.class) {
            System.out.println("test start");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("test end");
        }
    }
}
public class MyThread3 extends Thread{
    public void run() {
        Sync2 sync = new Sync2();
        sync.test();
    }

    public static void main(String[] args) {
        for (int i = 0; i < 3; ++i) {
            Thread thread = new MyThread3();
            thread.start();
        }
    }
}

执行结果

test start
test end
test start
test end
test start
test end

synchronized的两大不足

由于我们没办法设置synchronized关键字在获取锁的时候等待时间,所以synchronized可能会导致线程为了加锁而无限期地处于阻塞状态
使用synchronized关键字等同于使用了互斥锁,即其他线程都无法获得锁对象的访问权。这种策略对于读多写少的应用而言是很不利的,因为即使多个读者看似可以并发运行,但他们实际上还是串行的,并将最终导致并发性能的下降。
虽然synchronized已经作为一个关键字被固化在Java语言中了,但它只提供了一种相当保守的线程安全策略,且该策略开放给程序员的控制能力极弱

转发来自https://www.cnblogs.com/kaituorensheng/p/10079916.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值