线程安全性
来源:互联网 发布:atmega dip封装单片机 编辑:程序博客网 时间:2024/05/16 07:13
竞态条件与锁
当某个计算结果的正确性取决于多个线程执行的顺序时,就会发生竞态条件。常见的竞态类型是先检查后执行。
先检查后执行的一种常见情况是延迟初始化。
public class LazyInitRace{ private People people=null; public People getInstance(){ if(people==null){ people=new People(); } return people; }}
这就包含一个竞态条件,在people未被实例化前,当多个线程都访问getInstance()时,就可能会得到不同的结果。如果不在同一瞬间调用这个方法,就不会出现问题。在people被实例化之后,多次同时访问这个方法,也不会出现问题。
要避免竞态问题,就必须在某个线程修改改变量时,通过某种方式防止其它线程使用这个变量,也就是保证修改操作的原子性。
加锁是java内置的确保原子性的机制。
synchronized关键字加锁:
public class TT{ private Integer a=4; public static synchronized void do33(){ } public synchronized void do34(){ } public synchronized void do35(){ synchronized(a){ } }}以上第一个synchronized是对TT的Class对象加锁,每一个类的字节码文件被加载到内存中以后,就会生成一个Class对象。第二个synchronized是对创建的TT对象加锁,比如TT t=new TT();那么这个锁就对t生效。第三个synchronized是对a对象加锁。
java 的内置锁是一种互斥锁。
java的锁是可以重入的,也就是说,当前线程持有了某个对象的锁,在线程中再次获取该对象的锁,是可以成功的。例子如下:
public class T2{ public synchronized void t1(){ System.out.println("t1执行了"); synchronized(this){ System.out.println("t1中的同步块执行了"); } } public static void main(String[] args){ T2 t=new T2(); t.t1(); }}例子2:public class Father { public synchronized void play(){ System.out.println("father play"); }}public class Son extends Father { public synchronized void play(){ System.out.println("son play"); super.play(); } public static void main(String[] args){ new Son().play(); }}
一种常见的加锁约定是,把所有的可变状态封装在对象内部。通过内置锁对所有访问可变状态的路径(类似于get,set的方法)进行同步。Vector等集合类采用了这种模式。
不过上面这种方式也是有缺陷的,如果以后新增了一个方法,能够访问和修改哪些可变的变量,却又忘记增加synchronized关键字进行同步,那么就可能出现问题。
线程安全的类所组成的操作很多时候也需要额外的同步,如下:
if(!vector.contains(a)) vector.add(a)
这就存在竞态条件,需要把这2个操作组成一个原子性操作。
阅读全文
0 0
- 线程安全性
- 线程安全性
- 线程安全性
- 线程安全性
- 线程安全性
- 线程安全性
- 线程安全性
- 线程安全性
- 线程安全性
- 线程安全性
- 线程安全性
- 线程安全性
- 线程安全性
- 线程安全性
- Servlet线程安全性问题
- STL 线程安全性
- Servlet线程安全性问题
- 什么是线程安全性
- Java内存区域
- Elasticsearch 数据搜索篇·【入门级干货】
- PPT控件 Spire.Presentation for .NET V2.8.35发布 | 支持设置演示幻灯片布局
- jQuery中event.stopPropagation()阻止事件冒泡及event.preventDefault()阻止默认行为
- adaboost学习(三)
- 线程安全性
- Leetcode OJ 2 Add Two Numbers [Medium]
- Laravel中Blade模板引擎子视图
- mysql定时任务demo
- 存储过程游标使用
- [iOS 仿QQ消息推送框
- libcurl库使用一小下
- alembic 使用
- 数据库并发事务存在的问题(脏读、不可重复读、幻读等)