java基础-多线程的安全问题
2015-12-14 17:29
232 查看
在实际应用中,我们通常会遇到多线程安全问题, 涉及到两个因素:
1,多个线程在操作共享数据。
2,有多条语句对共享数据进行运算。
原因:这多条语句,在某一个时刻被一个线程执行时,还没有执行完,就被其他线程执行了。
解决办法:
对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不可以参与执行。
Java 对于多线程的安全提供了专业的解决方式。线程的同步是保证多线程安全访问竞争资源的一种手段,对于同步,在具体的Java代码中需要完成一下两个操作:
1.把竞争访问的资源标识为private;
2.同步哪些修改变量的代码,使用synchronized关键字同步方法或代码。
格式:
synchronized(对象) { // 任意对象都可以。这个对象就是锁。
需要被同步的代码;
}
同步的前提:
1、必须要有两个或者两个以上的线程运行;
2、必须是多个线程使用同一个锁;
好处:解决了多线程的安全问题;
弊端:多个线程需要判断锁,较为消耗资源;
注意: 非静态同步函数的对象锁为this,静态同步函数所使用的锁是该方法所在类的字节码文件对象,即类名.class,静态方法里的同步锁都是使用的是类的字节码对象 }
下面这个例子就是使用同步解决安全性问题
程序运行结果为
用到线程的同步,随之可能会带来死锁问题。
导致死锁的原因:两个线程互相等待竞争资源,导致两边都无法得到资源,而使自己无法运行。
导致死锁的根源在于不适当的运用synchronized来管理线程对特定对象的访问。解决死锁的方法有:
1、撤消陷于死锁的全部进程;
2、逐个撤消陷于死锁的进程,直到死锁不存在;
3、从陷于死锁的进程中逐个强迫放弃所占用的资源,直至死锁消失。
4、从另外一些进程那里强行剥夺足够数量的资源分配给死锁进程,以解除死锁状态
关于sleep方法,wait方法、jion方法
sleep方法与wait方法的区别:
sleep方法是静态方法,wait方法是非静态方法。
sleep方法在时间到后会自己“醒来”,但wait不能,必须由其它线程通过notify(All)方法让它“醒来”。
sleep方法通常用在不需要等待资源情况下的阻塞,像等待线程、数据库连接的。情况一般用wait。
Sleep:线程会释放执行权,但是不释放锁。wait:线程会释放执行权,而且线程会释放锁。
sleep/wait与yeld方法的区别:
调用sleep或wait方法后,线程即进入block状态,而调用yeld方法后,线程进入runnable状态。
wait与join方法的区别:
wait方法体现了线程之间的互斥关系,而join方法体现了线程之间的同步关系。
wait方法必须由其它线程来解锁,而join方法不需要,只要被等待线程执行完毕,当前线程自动变为就绪。
join方法的一个用途就是让子线程在完成业务逻辑执行之前,主线程一直等待直到所有子线程执行完毕。
wait和sleep区别: 分析这两个方法:从执行权和锁上来分析:
wait:可以指定时间也可以不指定时间。不指定时间,只能由对应的notify或者
notifyAll来唤醒。 notifyAll() 方法,起到的是一个通知作用,不释放锁,也不获取锁。只是告诉该对象上等待的线程可以竞争执行了
sleep:必须指定时间,时间到自动从冻结状态转成运行状态(临时阻塞状态)。
wait:线程会释放执行权,而且线程会释放锁。
Sleep:线程会释放执行权,但是不释放锁。
1,多个线程在操作共享数据。
2,有多条语句对共享数据进行运算。
原因:这多条语句,在某一个时刻被一个线程执行时,还没有执行完,就被其他线程执行了。
解决办法:
对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不可以参与执行。
Java 对于多线程的安全提供了专业的解决方式。线程的同步是保证多线程安全访问竞争资源的一种手段,对于同步,在具体的Java代码中需要完成一下两个操作:
1.把竞争访问的资源标识为private;
2.同步哪些修改变量的代码,使用synchronized关键字同步方法或代码。
格式:
synchronized(对象) { // 任意对象都可以。这个对象就是锁。
需要被同步的代码;
}
同步的前提:
1、必须要有两个或者两个以上的线程运行;
2、必须是多个线程使用同一个锁;
好处:解决了多线程的安全问题;
弊端:多个线程需要判断锁,较为消耗资源;
注意: 非静态同步函数的对象锁为this,静态同步函数所使用的锁是该方法所在类的字节码文件对象,即类名.class,静态方法里的同步锁都是使用的是类的字节码对象 }
下面这个例子就是使用同步解决安全性问题
public class SynchronizedThread2 { public static void main(String[] args) { User u = new User("wankun", 100); //创建用户对象,设定姓名和账户余额 MyThread t1 = new MyThread("线程1", u, 10); //创建自定义线程, MyThread t2 = new MyThread("线程2", u, -50); MyThread t3 = new MyThread("线程3", u, 28); t1.start(); //执行线程, t2.start(); t3.start(); } } class MyThread extends Thread { //自定义线程,设置线程的工作 private User wk; //竞争访问的资源定义为私有 private int y = 0; //竞争访问的资源定义为私有 MyThread(String name, User wk, int y) { super(name); this.wk = wk; this.y = y; } public void run() { //复写run方法,调用use类中的oper方法,更改wk对象的账户余额 wk.oper(y); //oper方法中含有多条语句,所以oper方法需要使用同步方法的形式来解决安全问题 } } class User { //账户类 private String code; //竞争访问的资源定义为私有 private int cash; //竞争访问的资源定义为私有 User(String code, int cash) { this.code = code; this.cash = cash; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public synchronized void oper(int x) { //业务方法,使用了synchronized关键字同步方法,使只有同一时间内只有一个线程可以使用该方法,从而解决多线程安全问题 try { Thread.sleep(10); //程序休眠10毫秒 this.cash += x; System.out.println(Thread.currentThread().getName() + "运行 ,增加“" + x + "”,当前余额为:" + cash); Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } }
程序运行结果为
用到线程的同步,随之可能会带来死锁问题。
导致死锁的原因:两个线程互相等待竞争资源,导致两边都无法得到资源,而使自己无法运行。
导致死锁的根源在于不适当的运用synchronized来管理线程对特定对象的访问。解决死锁的方法有:
1、撤消陷于死锁的全部进程;
2、逐个撤消陷于死锁的进程,直到死锁不存在;
3、从陷于死锁的进程中逐个强迫放弃所占用的资源,直至死锁消失。
4、从另外一些进程那里强行剥夺足够数量的资源分配给死锁进程,以解除死锁状态
关于sleep方法,wait方法、jion方法
sleep方法与wait方法的区别:
sleep方法是静态方法,wait方法是非静态方法。
sleep方法在时间到后会自己“醒来”,但wait不能,必须由其它线程通过notify(All)方法让它“醒来”。
sleep方法通常用在不需要等待资源情况下的阻塞,像等待线程、数据库连接的。情况一般用wait。
Sleep:线程会释放执行权,但是不释放锁。wait:线程会释放执行权,而且线程会释放锁。
sleep/wait与yeld方法的区别:
调用sleep或wait方法后,线程即进入block状态,而调用yeld方法后,线程进入runnable状态。
wait与join方法的区别:
wait方法体现了线程之间的互斥关系,而join方法体现了线程之间的同步关系。
wait方法必须由其它线程来解锁,而join方法不需要,只要被等待线程执行完毕,当前线程自动变为就绪。
join方法的一个用途就是让子线程在完成业务逻辑执行之前,主线程一直等待直到所有子线程执行完毕。
wait和sleep区别: 分析这两个方法:从执行权和锁上来分析:
wait:可以指定时间也可以不指定时间。不指定时间,只能由对应的notify或者
notifyAll来唤醒。 notifyAll() 方法,起到的是一个通知作用,不释放锁,也不获取锁。只是告诉该对象上等待的线程可以竞争执行了
sleep:必须指定时间,时间到自动从冻结状态转成运行状态(临时阻塞状态)。
wait:线程会释放执行权,而且线程会释放锁。
Sleep:线程会释放执行权,但是不释放锁。
相关文章推荐
- 浅谈JAVA常用分布式实现方式及优缺点
- Java Web开发之配置一个Servlet接收多个接口
- JDK的SPI
- Java泛型详解
- spring结合mockito
- 使用eclipse生成文档(javadoc)主要有三种方法:
- Eclipse热交换代码失败
- Java Thread.join()详解
- java.lang.OutOfMemoryError异常解决方法
- 深度分析Java的ClassLoader机制(源码级别)
- Eclipse 运行弹出A Java Exception has occurred.并报错Exception in thread
- Java中throws与throw的区别
- Java基础编程之统计字符个数
- java十分钟速懂知识点——System类
- javaweb页面嵌入天气显示
- springmvc url 路径映射
- java基础之 多态
- 从头认识java-13.7 什么时候使用泛型?
- spring依赖注入理解
- Eclipse解决启动慢