java线程冲突问题——不安全的线程例子
2013-09-26 20:41
295 查看
#Java线程安全问题 在平时编程中,我们会经常用到多线程,尤其是android中,但多线程也特别容易带来问题,比如线程冲突、死锁等问题,为了加深理解,我们先来回顾一下线程冲突问题。 ##线程冲突 ```java public class UserStat { int userCount; public int getUserCount() { return userCount; } public void increment() { userCount++; } public void decrement() { userCount--; } } ``` 假设当一个线程正在递增**userCount**变量时,另一个线程则试图通过调用**getUserCount**来读取该变量的值,这时会发生什么情况呢?请记住,**userCount++**语句实际上是由3个连续的步骤组成的: - 读取**userCount**的值,并将它保存在某个临时储存装置中 - 递增这个值 - 降递增的值写回到**userCount**中 假设有一个线程负责读取和递增**userCount**的值。在它有机会存储递增的值之前,另一个线程会读取它,并且得到的是旧值。当第二个线程最终得到机会写入**userCount**时,它会替换掉第一个线程的递增值。两个非原子的操作在不同的线程中运行,却操作同一个数据,其中的交叉就称作线程冲突。 ##不安全的线程例子 下面我们从一个不安全的例子开始,分析一下线程冲突。 ```java public class UnSafeThreadDemo { public UnSafeThreadDemo() { } /** * @author xuyan */ public static void main(String[] args) throws InterruptedException { final UserStat us = new UnSafeThreadDemo().new UserStat(); Thread th1 = new Thread("th1") { @Override public void run() { System.out.println(us.getUserCount() + " " + super.getName()); } }; Thread th2 = new Thread("th2") { @Override public void run() { System.out.println(us.getUserCount() + " " + super.getName()); } }; th1.start(); // Thread.sleep(100); th2.start(); } class UserStat { int userCount; public int getUserCount() { return userCount++; } } } ``` - 如果不执行Thread.sleep(1000); - 偶尔结果为: - 0 th2 - 0 th1 - 如果执行Thread.sleep(1000); - 结果为: - 0 th1 - 1 th2 对于这样的多线程冲突问题,我们采用一种常规的解决方法,就是同步机制。让我们对操作加synchronized关键字: ```java class UserStat { int userCount; public synchronized int getUserCount() { return userCount++; } } ``` 注:synchronized 方法控制对类成员变量的访问: 每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行,否则所属 线程阻塞 ,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可 执行状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)。
相关文章推荐
- java线程冲突问题——不安全的线程例子
- java线程安全问题之静态变量、实例变量、局部变量
- java再复习——线程的安全问题以及同步
- Java 线程通信的安全问题(同步)
- java线程安全之synchronized同步代码块解决脏读问题(四)
- java之线程安全问题
- java线程安全之死锁问题
- Java SimpleDateFormat 线程不安全问题及解决方法
- 设计模式——单例模式(Java)——考虑多线程环境下的线程安全问题
- java线程安全问题之静态变量、实例变量、局部变量
- (47)Java学习笔记——多线程 / 线程的安全问题
- java中如何解决线程不安全的问题呢?
- java线程安全问题之静态变量、实例变量、局部变量
- Java赋值的线程安全问题
- java线程的同步安全问题三种解决办法
- java线程安全问题之静态成员变量、实例成员变量、局部变量
- java线程安全问题之静态变量、实例变量、局部变量
- Java8新特性-014-传统时间API的线程安全问题
- java线程安全问题之静态变量、实例变量、局部变量
- java线程安全问题