synchronized锁住的是代码还是对象
2023-09-27 14:25:20 时间
不同的对象
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(); } } }
执行结果
test start test start test start test end test end test end
现象
在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(); } }
执行结果
hi.... test start hi.... hi.... test end test start test end test start test end
现象
可以看到当他们共用一个对象的时候,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语言中了,但它只提供了一种相当保守的线程安全策略,且该策略开放给程序员的控制能力极弱
参考
相关文章
- BEGINNING SHAREPOINT® 2013 DEVELOPMENT 第9章节--client对象模型和REST APIs概览 Windows Phone
- MVC5中Model层开发数据注解 EF Code First Migrations数据库迁移 C# 常用对象的的修饰符 C# 静态构造函数 MSSQL2005数据库自动备份问题(到同一个局域网上的另一台电脑上) MVC 的HTTP请求
- 【Java】理解封装、继承、多态和对象数组的综合实例(简易的租车系统,附代码)
- ES6(九)对象的扩展
- python⾯向对象编程-多态
- wps 论文查重 对象类型没有word
- SAP MM 一个含有多个账号分配对象的行项目的PO及其收货
- 多重继承及虚继承中对象内存的分布
- 《.NET程序员面试秘笈》----面试题2 用代码描述类和对象的区别
- Java将引入新的对象类型来解决内存利用问题
- Java对象转JSON时如何动态的增删改查属性
- 待解决问题:c++栈对象的析构、虚拟内存与内存管理的关系、内存管理的解决方案。
- JS内置对象之Math(附代码及演示效果)
- Qt之美(一):d指针/p指针详解(解释二进制兼容,以及没有D指针就会崩溃的例子。有了D指针,所使用的对象大小永远不会改变,它就是该指针的大小。这个指针就被称作D指针)good
- Qt笔记——元对象系统
- 危险代码:如何使用Unsafe操作内存中的Java类和对象
- JS对象深入剖析